//////////////////////////////////////////////////////////////////////
//
//	Crytek CryENGINE Source code
//	
//	File:Renderer.cpp
//  Description: Abstract renderer API
//
//	History:
//	-Feb 05,2001:Originally Created by Marco Corbetta
//	-: taken over by Andrey Honich
//.
//////////////////////////////////////////////////////////////////////

#include "StdAfx.h"

#include "Shadow_Renderer.h"
#include "IStatObj.h"
#include "I3DEngine.h"
#include "IMovieSystem.h"
#include "IIndexedMesh.h"
#include "CREParticle.h"
#include "BitFiddling.h"															// IntegerLog2()	
#include "ImageExtensionHelper.h"											// CImageExtensionHelper
#if !defined(EXCLUDE_SQUISH_SDK)
#include "Textures/Image/Squish/squish.h"							// CompressImage
#endif
#include "ResourceCompilerHelper.h"                   // CResourceCompilerHelper

#include "Textures/Image/CImage.h"
#include "Textures/Image/JpgImage.h"
#include "Textures/TextureManager.h"
#include "../CryCommon/auto_vector.h"
#include "../CryCommon/branchmask.h"
#include "PostProcess/PostEffects.h"
#include "RenderObjectDefines.h"

#include "IntroMovieRenderer.h"
#if SUPPORT_RENDER_TO_CONTROLLER
#include "IRenderToScreenOnController.h";
#include "RenderToDRC.h"
#endif

#ifdef WIN64
	#pragma warning(disable: 4244)
#endif

#if defined(LINUX)
#include "ILog.h"
#endif

#include "Textures/Image/CompressedImage.h"

#if !defined(NULL_RENDERER) && !defined(gringo)
# ifdef WIN32
#	 pragma message (">>> include lib: nvDXTlib")
#	  ifdef WIN64
#		  pragma comment ( lib, "../../../Tools/nvDXTLibrary/x64/Release/nvDXTLibrary.lib" )
#	  else // WIN64
#		  pragma comment ( lib, "../../../Tools/nvDXTLibrary/Win32/Release/nvDXTLibrary.lib" )
#	  endif // WIN64
# endif // WIN32
#endif // NULL_RENDERER


namespace 
{ 
	class CConditonalLock
	{
		CryCriticalSection &_lock; 
		bool _bActive; 
	public: 
		CConditonalLock(CryCriticalSection& lock, bool bActive) 
			: _lock(lock), _bActive(bActive)
		{ if (_bActive) _lock.Lock(); }
		~CConditonalLock() 
		{ if (_bActive) _lock.Unlock(); }
	};
} 


bool QueryIsFullscreen();

//////////////////////////////////////////////////////////////////////////
// Globals.
//////////////////////////////////////////////////////////////////////////
CRenderer *gRenDev = NULL;

#define RENDERER_DEFAULT_FONT "Fonts/default.xml"

// The defined mesh pool size for PS3 



#if defined(DIRECT3D9) && !defined(RENDERER_DEFAULT_MESHPOOLSIZE)
# define RENDERER_DEFAULT_MESHPOOLSIZE (0U)
#endif
#if !defined(RENDERER_DEFAULT_MESHPOOLSIZE)
# define RENDERER_DEFAULT_MESHPOOLSIZE (0U) 
#endif

#define EYEADAPTIONBASEDEFAULT		0.25f					// only needed for Crysis

#if defined(_LIB)
	extern int g_CpuFlags;
#else
	int g_CpuFlags;
#endif

#ifndef XENON
#include <CrtDebugStats.h>
#endif

//////////////////////////////////////////////////////////////////////////
// Pool allocators.
//////////////////////////////////////////////////////////////////////////
SDynTexture_PoolAlloc* g_pSDynTexture_PoolAlloc = 0;
//////////////////////////////////////////////////////////////////////////

// per-frame profilers: collect the information for each frame for 
// displaying statistics at the beginning of each frame
//#define PROFILER(ID,NAME) DEFINE_FRAME_PROFILER(ID,NAME)
//#include "FrameProfilers-list.h"
//#undef PROFILER

///

/// Used by console auto completion.
struct STextureNameAutoComplete : public IConsoleArgumentAutoComplete
{
	virtual int GetCount() const
	{
		SResourceContainer* pRC = CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
		if(!pRC)
			return 0;
		return pRC->m_RMap.size();
	}
	virtual const char* GetValue( int nIndex ) const
	{
		SResourceContainer* pRC = CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
		if(!pRC || pRC->m_RMap.empty())
			return "";
		nIndex %= pRC->m_RMap.size();
		ResourcesMap::const_iterator it = pRC->m_RMap.begin();
		std::advance(it, nIndex);
		CTexture *pTex = (CTexture *)it->second;
		if (pTex)
				return pTex->GetSourceName();
		return "";
	}
} g_TextureNameAutoComplete;

// Common render console variables
AllocateConstIntCVar(CRenderer,CV_r_PostProcess);
AllocateConstIntCVar(CRenderer,CV_r_NightVision);
float CRenderer::CV_r_NightVisionFinalMul;
float CRenderer::CV_r_NightVisionAmbientMul;
float CRenderer::CV_r_NightVisionBrightLevel;
float CRenderer::CV_r_NightVisionViewDist;
float CRenderer::CV_r_NightVisionSonarRadius;
float CRenderer::CV_r_NightVisionSonarLifetime;
float CRenderer::CV_r_NightVisionSonarMultiplier;
float CRenderer::CV_r_NightVisionCamMovNoiseAmount;
float CRenderer::CV_r_NightVisionCamMovNoiseBlendSpeed;
float CRenderer::CV_r_dofMinZ;
float CRenderer::CV_r_dofMinZScale;
float CRenderer::CV_r_dofMinZBlendMult;
#ifndef PS3
	int CRenderer::CV_r_vsync;
#endif
AllocateConstIntCVar(CRenderer,CV_e_DebugTexelDensity);
int CRenderer::CV_r_flush;
AllocateConstIntCVar(CRenderer,CV_r_stats);
AllocateConstIntCVar(CRenderer,CV_r_log);
AllocateConstIntCVar(CRenderer,CV_r_logTexStreaming);
AllocateConstIntCVar(CRenderer,CV_r_logShaders);
AllocateConstIntCVar(CRenderer,CV_r_logVBuffers);
AllocateConstIntCVar(CRenderer,CV_r_logVidMem);
AllocateConstIntCVar(CRenderer,CV_r_predicatedtiling);
AllocateConstIntCVar(CRenderer,CV_r_testSplitScreen);
AllocateConstIntCVar(CRenderer,CV_r_SplitScreenActive);
int CRenderer::CV_r_DeferredShadingSortLights;
int CRenderer::CV_r_msaa;
int CRenderer::CV_r_msaa_samples;
int CRenderer::CV_r_msaa_quality;
int CRenderer::CV_r_msaa_debug;
int CRenderer::CV_r_msaa_amd_resolvessubresource;
int CRenderer::CV_r_BreakOnError;

AllocateConstIntCVar(CRenderer,CV_r_multithreaded);
int CRenderer::CV_r_multigpu;
AllocateConstIntCVar(CRenderer,CV_r_validateDraw);
AllocateConstIntCVar(CRenderer,CV_r_profileGPU);
#if defined(ENABLE_ACCURATE_RSX_PROFILING)
AllocateConstIntCVar(CRenderer,CV_r_ProfileRSX);	
#endif
int CRenderer::CV_r_CBStatic;
AllocateConstIntCVar(CRenderer,CV_r_CBStaticDebug);
AllocateConstIntCVar(CRenderer,CV_r_texturesstreaming);
AllocateConstIntCVar(CRenderer,CV_r_TexturesStreamingDebug);
AllocateConstIntCVar(CRenderer,CV_r_texturesstreamingnoupload);
AllocateConstIntCVar(CRenderer,CV_r_texturesstreamingonlyvideo);
int CRenderer::CV_r_texturesstreamingsync;
AllocateConstIntCVar(CRenderer,CV_r_texturesstreamingResidencyEnabled);
AllocateConstIntCVar(CRenderer,CV_r_texturesstreamingPostponeMips);
AllocateConstIntCVar(CRenderer,CV_r_texturesstreamingPostponeThresholdKB);
AllocateConstIntCVar(CRenderer,CV_r_texturesstreamingPostponeThresholdMip);
AllocateConstIntCVar(CRenderer,CV_r_texturesstreamingMinReadSizeKB);
float CRenderer::CV_r_texturesstreamingResidencyTimeTestLimit;
float CRenderer::CV_r_rain_maxviewdist;
float CRenderer::CV_r_rain_maxviewdist_deferred;
float CRenderer::CV_r_measureoverdrawscale;
float CRenderer::CV_r_texturesstreamingResidencyTime;
float CRenderer::CV_r_texturesstreamingResidencyThrottle;
AllocateConstIntCVar(CRenderer,CV_r_texturesstreamingmipfading);
int CRenderer::CV_r_texturesstreampoolsize;
int CRenderer::CV_r_texturesstreampoolsyssize;
int CRenderer::CV_r_texturesstreampoolfragmentationcount;
int CRenderer::CV_r_texturesstreampooldefragmentation;
int CRenderer::CV_r_texturesskiplowermips;
int CRenderer::CV_r_rendertargetpoolsize;
float CRenderer::CV_r_TexturesStreamingMaxRequestedMB;
int CRenderer::CV_r_TexturesStreamingMaxRequestedJobs;
float CRenderer::CV_r_TexturesStreamingMipBias;
int CRenderer::CV_r_TexturesStreamingMipClampDVD;
int CRenderer::CV_r_TexturesStreamingDisableNoStreamDuringLoad;
#if !defined(XENON) && !defined(PS3) && !defined(CAFE)
int CRenderer::CV_r_textureswarmup;
#endif
float CRenderer::CV_r_TextureLodDistanceRatio;
int CRenderer::CV_r_dyntexmaxsize;
int CRenderer::CV_r_dyntexatlascloudsmaxsize;
int CRenderer::CV_r_dyntexatlasspritesmaxsize;
int CRenderer::CV_r_dyntexatlasvoxterrainsize;
int CRenderer::CV_r_dyntexatlasdyntexsrcsize;

AllocateConstIntCVar(CRenderer,CV_r_texpostponeloading);
AllocateConstIntCVar(CRenderer,CV_r_texpreallocateatlases);
int CRenderer::CV_r_texatlassize;
int CRenderer::CV_r_texminanisotropy;
int CRenderer::CV_r_texmaxanisotropy;
AllocateConstIntCVar(CRenderer,CV_r_texmaxsize);
AllocateConstIntCVar(CRenderer,CV_r_texminsize);
AllocateConstIntCVar(CRenderer,CV_r_texbumpresolution);
AllocateConstIntCVar(CRenderer,CV_r_texresolution);
int CRenderer::CV_r_texskyresolution;
AllocateConstIntCVar(CRenderer,CV_r_texgrid);
AllocateConstIntCVar(CRenderer,CV_r_texlog);
AllocateConstIntCVar(CRenderer,CV_r_texnoload);

AllocateConstIntCVar(CRenderer,CV_r_debugrendermode);
AllocateConstIntCVar(CRenderer,CV_r_debugrefraction);
float CRenderer::CV_r_DebugVoxTerrainX;
float CRenderer::CV_r_DebugVoxTerrainY;

AllocateConstIntCVar(CRenderer,CV_r_deferredshadingLightVolumes);
AllocateConstIntCVar(CRenderer,CV_r_deferredDecals);
AllocateConstIntCVar(CRenderer,CV_r_deferredDecalsDebug);

AllocateConstIntCVar(CRenderer,CV_r_deferredshadingDBTstencil);
AllocateConstIntCVar(CRenderer,CV_r_DeferredShadingScissor);
AllocateConstIntCVar(CRenderer,CV_r_DeferredShadingDepthBoundsTest);
AllocateConstIntCVar(CRenderer,CV_r_DeferredShadingDebug);
AllocateConstIntCVar(CRenderer,CV_r_DeferredShadingAmbient);
AllocateConstIntCVar(CRenderer,CV_r_DeferredShadingEnvProbes);
AllocateConstIntCVar(CRenderer,CV_r_DeferredShadingLights);
AllocateConstIntCVar(CRenderer,CV_r_DeferredShadingStencilPrepass);
AllocateConstIntCVar(CRenderer,CV_r_DeferredShadingHeightBasedAmbient);

float CRenderer::CV_r_DeferredShadingLightLodRatio;
float CRenderer::CV_r_DeferredShadingLightStencilRatio;

AllocateConstIntCVar(CRenderer,CV_r_LightPropagationVolumes);

int CRenderer::CV_r_HDRRendering;
AllocateConstIntCVar(CRenderer,CV_r_HDRDebug);
float CRenderer::CV_r_HDRLevel;
float CRenderer::CV_r_HDROffset;
float CRenderer::CV_r_HDRBrightOffset;
float CRenderer::CV_r_HDRBrightThreshold;
float CRenderer::CV_r_HDRBrightLevel;
float CRenderer::CV_r_HDRSCurveMin;
float CRenderer::CV_r_HDRSCurveMax;
float CRenderer::CV_r_HDRSaturation;
float CRenderer::CV_r_HDRBrightness;
float CRenderer::CV_r_HDRBlueShift;
AllocateConstIntCVar(CRenderer,CV_r_HDRVignetting);
AllocateConstIntCVar(CRenderer,CV_r_HDRTexFormat);
AllocateConstIntCVar(CRenderer,CV_r_HDRForceUpdateTextures);
AllocateConstIntCVar(CRenderer,CV_r_HDRRangeAdapt);

float CRenderer::CV_r_HDRRangeAdaptMax;
float CRenderer::CV_r_HDRRangeAdaptMaxRange;
float CRenderer::CV_r_HDRRangeAdaptLBufferMaxRange;
float CRenderer::CV_r_HDRRangeAdaptLBufferMax;		
float CRenderer::CV_r_HDREyeAdaptationFactor;
float CRenderer::CV_r_HDREyeAdaptationBase;
float CRenderer::CV_r_HDREyeAdaptationSpeed;
int CRenderer::CV_r_HDREyeAdaptionCache;
int CRenderer::CV_r_HDREyeAdaptationLocal;
float CRenderer::CV_r_HDRRangeAdaptationSpeed;
float CRenderer::CV_r_HDRGrainAmount;
float CRenderer::CV_r_HDRBloomMul;

AllocateConstIntCVar(CRenderer,CV_r_geominstancing);
AllocateConstIntCVar(CRenderer,CV_r_geominstancingdebug);
AllocateConstIntCVar(CRenderer,CV_r_materialsbatching);

#if defined (TESSELLATION_RENDERER)
int CRenderer::CV_r_usepom;
int CRenderer::CV_r_WaterTessellationHW;
#endif
int CRenderer::CV_r_tessellationdebug;
float CRenderer::CV_r_tessellationtrianglesize;
float CRenderer::CV_r_displacementfactor;

int CRenderer::CV_r_batchtype;
int CRenderer::CV_r_geominstancingthreshold;
int CRenderer::m_iGeomInstancingThreshold=0;		// 0 means not set yet
bool CRenderer::m_bTerrainAOEnabled=false;		// false means not set yet


int CRenderer::CV_r_beams;
int CRenderer::CV_r_beamssoftclip;
int CRenderer::CV_r_beamshelpers;
int CRenderer::CV_r_beamsmaxslices;
float CRenderer::CV_r_beamsdistfactor;

AllocateConstIntCVar(CRenderer,CV_r_DebugLightVolumes);

AllocateConstIntCVar(CRenderer,CV_r_UseShadowsPool);

float CRenderer::CV_r_ShadowsBias;
float CRenderer::CV_r_ShadowsAdaptionRangeClamp;
float CRenderer::CV_r_ShadowsAdaptionSize;
float CRenderer::CV_r_ShadowsAdaptionMin;
float CRenderer::CV_r_ShadowsParticleKernelSize;
float CRenderer::CV_r_ShadowsParticleJitterAmount;
float CRenderer::CV_r_ShadowsParticleAnimJitterAmount;
float CRenderer::CV_r_ShadowsParticleNormalEffect;

AllocateConstIntCVar(CRenderer,CV_r_ShadowGenMode);
AllocateConstIntCVar(CRenderer,CV_capture_misc_render_buffers);

AllocateConstIntCVar(CRenderer,CV_r_ShadowsUseClipVolume);
int CRenderer::CV_r_shadowblur;
AllocateConstIntCVar(CRenderer,CV_r_shadowtexformat);
AllocateConstIntCVar(CRenderer,CV_r_ShadowsMaskResolution);
AllocateConstIntCVar(CRenderer,CV_r_ShadowsMaskDownScale);
AllocateConstIntCVar(CRenderer,CV_r_ShadowsDeferredMode);
AllocateConstIntCVar(CRenderer,CV_r_ShadowsStencilPrePass);



int CRenderer::CV_r_ShadowsDepthBoundNV;
int	CRenderer::CV_r_ShadowsPCFiltering;
AllocateConstIntCVar(CRenderer,CV_r_ShadowsForwardPass);
float CRenderer::CV_r_shadowbluriness;
float CRenderer::CV_r_shadow_jittering;
float CRenderer::CV_r_VarianceShadowMapBlurAmount;
int CRenderer::CV_r_ShadowPoolMaxTimeslicedUpdatesPerFrame;
AllocateConstIntCVar(CRenderer,CV_r_ShadowsGridAligned);
AllocateConstIntCVar(CRenderer,CV_r_ShadowGenGS);
AllocateConstIntCVar(CRenderer,CV_r_ShadowPass);
AllocateConstIntCVar(CRenderer,CV_r_ShadowGen);
AllocateConstIntCVar(CRenderer,CV_r_ShadowPoolMaxFrames);

float	CRenderer::CV_r_RenderMeshHashGridUnitSize;

int CRenderer::CV_r_SSAO;
int CRenderer::CV_r_SSAO_downscale;
float CRenderer::CV_r_SSAO_amount;
int CRenderer::CV_r_SSAO_quality;
float CRenderer::CV_r_SSAO_radius;
float CRenderer::CV_r_SSAO_contrast;
float CRenderer::CV_r_SSAO_temporalConvergence;
float CRenderer::CV_r_SSAO_smallradiusratio;
float CRenderer::CV_r_SSAO_largeradiusratio;
float CRenderer::CV_r_SSAO_brighteningmargin;

AllocateConstIntCVar(CRenderer,CV_r_TerrainAO);
AllocateConstIntCVar(CRenderer,CV_r_TerrainAO_FadeDist);

AllocateConstIntCVar(CRenderer,CV_r_debuglights);
AllocateConstIntCVar(CRenderer,CV_r_lightssinglepass);

AllocateConstIntCVar(CRenderer,CV_r_impostersdraw);
float CRenderer::CV_r_imposterratio;
int CRenderer::CV_r_impostersupdateperframe;
AllocateConstIntCVar(CRenderer,CV_r_shaderslazyunload);
AllocateConstIntCVar(CRenderer,CV_r_shadersdebug);
#if !defined (XENON) && !defined(PS3) && !defined(CAFE)
int CRenderer::CV_r_shaderscafe;
int CRenderer::CV_r_shadersxenon;
int CRenderer::CV_r_shadersps3;
int CRenderer::CV_r_shadersdx9;
int CRenderer::CV_r_shadersdx11;
#endif
AllocateConstIntCVar(CRenderer,CV_r_shadersignoreincludeschanging);
int CRenderer::CV_r_shaderspreactivate;
int CRenderer::CV_r_shadersintcompiler;
int CRenderer::CV_r_shadersnocompile;
AllocateConstIntCVar(CRenderer,CV_r_shadersediting);
AllocateConstIntCVar(CRenderer,CV_r_shaderscompileautoactivate);
int CRenderer::CV_r_shadersremotecompiler;
int CRenderer::CV_r_shadersasynccompiling;
int CRenderer::CV_r_shadersasyncactivation;
int CRenderer::CV_r_shadersasyncmaxthreads;
int CRenderer::CV_r_shaderscacheoptimiselog;
AllocateConstIntCVar(CRenderer,CV_r_shadersprecachealllights);
int CRenderer::CV_r_shaderssubmitrequestline;
int CRenderer::CV_r_shadersuseinstancelookuptable;
int CRenderer::CV_r_shaderslogcachemisses;

AllocateConstIntCVar(CRenderer,CV_r_optimisedlightsetup);

AllocateConstIntCVar(CRenderer,CV_r_meshprecache);
int CRenderer::CV_r_meshpoolsize;
int CRenderer::CV_r_meshvolatilepoolsize;

AllocateConstIntCVar(CRenderer,CV_r_ZPassDepthSorting);

int CRenderer::CV_r_usezpass;
AllocateConstIntCVar(CRenderer,CV_r_usealphablend);
AllocateConstIntCVar(CRenderer,CV_r_SoftAlphaTest);
AllocateConstIntCVar(CRenderer,CV_r_usehwskinning);
AllocateConstIntCVar(CRenderer,CV_r_usemateriallayers);
AllocateConstIntCVar(CRenderer,CV_r_usesoftparticles);
AllocateConstIntCVar(CRenderer,CV_r_useparticles_refraction);
AllocateConstIntCVar(CRenderer,CV_r_useparticles_glow);
AllocateConstIntCVar(CRenderer,CV_r_useparticles_halfres);
AllocateConstIntCVar(CRenderer,CV_r_useparticles_halfres_force);
AllocateConstIntCVar(CRenderer,CV_r_useparticles_halfres_min_coverage);
AllocateConstIntCVar(CRenderer,CV_r_useparticles_halfres_debug);
AllocateConstIntCVar(CRenderer,CV_r_useparticles_merge);
int CRenderer::CV_r_PostAA;
int CRenderer::CV_r_PostAAMode;
int CRenderer::CV_r_PostAAEdgeFilter;
int CRenderer::CV_r_PostAAStencilCulling;
#if !defined(PS3) && !defined(XENON) && !defined(CAFE)
AllocateConstIntCVar(CRenderer,CV_r_PostAAInEditingMode);
#endif
float CRenderer::CV_r_useparticles_giamount;

Vec2 CRenderer::s_overscanBorders(0, 0);

int CRenderer::CV_r_MotionBlur;
int CRenderer::CV_r_UseMergedPosts;
float CRenderer::CV_r_MotionBlurShutterSpeed;
float CRenderer::CV_r_MotionBlurMaxViewDist;
AllocateConstIntCVar(CRenderer,CV_r_MotionBlurFrameTimeScale);
AllocateConstIntCVar(CRenderer,CV_r_MotionBlurAdaptiveSampling);
int CRenderer::s_AllowMotionBlur;				// potentially adjusted internal state of r_motionblur

float CRenderer::CV_r_cloakLightScale;
float CRenderer::CV_r_cloakTransitionLightScale;
int		CRenderer::CV_r_cloakFadeByDist;
float CRenderer::CV_r_cloakFadeLightScale;
float CRenderer::CV_r_cloakFadeStartDistSq;
float CRenderer::CV_r_cloakFadeEndDistSq;
float CRenderer::CV_r_cloakFadeMinValue;
int		CRenderer::CV_r_cloakRefractionFadeByDist;
float CRenderer::CV_r_cloakRefractionFadeStartDistSq;
float CRenderer::CV_r_cloakRefractionFadeEndDistSq;
float CRenderer::CV_r_cloakRefractionFadeMinValue;
float CRenderer::CV_r_cloakMinLightValue;
float CRenderer::CV_r_cloakHeatScale;
int CRenderer::CV_r_cloakRenderInThermalVision;
float CRenderer::CV_r_cloakMinAmbientOutdoors;
float CRenderer::CV_r_cloakMinAmbientIndoors;
float CRenderer::CV_r_cloakSparksAlpha;
float CRenderer::CV_r_cloakInterferenceSparksAlpha;
float CRenderer::CV_r_cloakHighlightStrength;
float CRenderer::CV_r_armourPulseSpeedMultiplier;
float CRenderer::CV_r_maxSuitPulseSpeedMultiplier;

AllocateConstIntCVar(CRenderer,CV_r_customvisions);
AllocateConstIntCVar(CRenderer,CV_r_DebugLayerEffect); 

AllocateConstIntCVar(CRenderer,CV_r_snow);
AllocateConstIntCVar(CRenderer,CV_r_snow_halfres);
AllocateConstIntCVar(CRenderer,CV_r_snow_displacement);
AllocateConstIntCVar(CRenderer,CV_r_snowFlakeClusters);
AllocateConstIntCVar(CRenderer,CV_r_rain);
AllocateConstIntCVar(CRenderer,CV_r_rain_ignore_nearest);
float CRenderer::CV_r_rainamount;
int CRenderer::CV_r_rainLayersPerFrame;
float CRenderer::CV_r_rainDistMultiplier;
float CRenderer::CV_r_rainOccluderSizeTreshold;

int CRenderer::CV_r_SSReflections;
float CRenderer::CV_r_SSReflCutoff;
float CRenderer::CV_r_SSReflExp;
int CRenderer::CV_r_ssdo;
float CRenderer::CV_r_ssdoRadius;
float CRenderer::CV_r_ssdoRadiusMin;
float CRenderer::CV_r_ssdoRadiusMax;
float CRenderer::CV_r_ssdoAmount;
float CRenderer::CV_r_ssdoAmbientAmount;
    
AllocateConstIntCVar(CRenderer,CV_r_dof);
AllocateConstIntCVar(CRenderer,CV_r_DofBokeh);
int CRenderer::CV_r_DofBokehQuality;
AllocateConstIntCVar(CRenderer,CV_r_dof_stencil_prepass);

AllocateConstIntCVar(CRenderer,CV_r_measureoverdraw);
AllocateConstIntCVar(CRenderer,CV_r_printmemoryleaks);
AllocateConstIntCVar(CRenderer,CV_r_releaseallresourcesonexit);

int   CRenderer::CV_r_rc_autoinvoke;  

AllocateConstIntCVar(CRenderer,CV_r_glow);
int CRenderer::CV_r_glowanamorphicflares;

int CRenderer::CV_r_refraction;
int CRenderer::CV_r_sunshafts; 
AllocateConstIntCVar(CRenderer,CV_r_pointlightshafts); 

AllocateConstIntCVar(CRenderer,CV_r_SonarVision);
AllocateConstIntCVar(CRenderer,CV_r_ThermalVision);
float CRenderer::CV_r_ThermalVisionViewDistance;
AllocateConstIntCVar(CRenderer,CV_r_ThermalVisionViewCloakFrequencyPrimary);
AllocateConstIntCVar(CRenderer,CV_r_ThermalVisionViewCloakFrequencySecondary);
float CRenderer::CV_r_ThermalVisionViewCloakFlickerMinIntensity;
float CRenderer::CV_r_ThermalVisionViewCloakFlickerMaxIntensity;

AllocateConstIntCVar(CRenderer,CV_r_PostProcessParamsBlending);
int CRenderer::CV_r_PostProcessReset;
AllocateConstIntCVar(CRenderer,CV_r_PostProcessFilters);
AllocateConstIntCVar(CRenderer,CV_r_PostProcessGameFx);
float CRenderer::CV_r_PostprocessParamsBlendingTimeScale;
AllocateConstIntCVar(CRenderer,CV_r_PostProcessHUD3D);
AllocateConstIntCVar(CRenderer,CV_r_PostProcessHUD3DDebugView);
int CRenderer::CV_r_PostProcessHUD3DCache;
float CRenderer::CV_r_PostProcessHUD3DShadowAmount;
float CRenderer::CV_r_PostProcessHUD3DGlowAmount;
AllocateConstIntCVar(CRenderer,CV_r_PostProcessHUD3DStencilClear);
AllocateConstIntCVar(CRenderer,CV_r_PostProcessNanoGlassDebugView);

AllocateConstIntCVar(CRenderer,CV_r_showgammareference);

int CRenderer::CV_r_colorgrading;
int CRenderer::CV_r_colorgrading_selectivecolor;
AllocateConstIntCVar(CRenderer,CV_r_colorgrading_levels);
AllocateConstIntCVar(CRenderer,CV_r_colorgrading_filters);
int CRenderer::CV_r_colorgrading_charts;
int CRenderer::CV_r_ColorgradingChartsCache;

AllocateConstIntCVar(CRenderer,CV_r_fur);

AllocateConstIntCVar(CRenderer,CV_r_cloudsupdatealways);
AllocateConstIntCVar(CRenderer,CV_r_cloudsdebug);

AllocateConstIntCVar(CRenderer,CV_r_showdyntextures);
int CRenderer::CV_r_ShowDynTexturesMaxCount;
ICVar *CRenderer::CV_r_ShowDynTexturesFilter;
AllocateConstIntCVar(CRenderer,CV_r_shownormals);
AllocateConstIntCVar(CRenderer,CV_r_showlines);
float CRenderer::CV_r_normalslength;
AllocateConstIntCVar(CRenderer,CV_r_showtangents);
AllocateConstIntCVar(CRenderer,CV_r_showtimegraph);
AllocateConstIntCVar(CRenderer,CV_r_DebugFontRendering);
AllocateConstIntCVar(CRenderer,CV_profileStreaming);
AllocateConstIntCVar(CRenderer,CV_r_graphstyle);
AllocateConstIntCVar(CRenderer,CV_r_showmt);
AllocateConstIntCVar(CRenderer,CV_r_showbufferusage);

ICVar* CRenderer::CV_r_ShaderCompilerServer;
ICVar* CRenderer::CV_r_ShaderEmailTags;
int CRenderer::CV_r_ShaderCompilerPort;
int CRenderer::CV_r_ShaderCompilerDontCache;
int CRenderer::CV_r_flares;

//int CRenderer::CV_r_envcmwrite;
int CRenderer::CV_r_envcmresolution;
int CRenderer::CV_r_envtexresolution;
float CRenderer::CV_r_waterupdateFactor;
float CRenderer::CV_r_waterupdateDistance;
float CRenderer::CV_r_envlcmupdateinterval;
float CRenderer::CV_r_envcmupdateinterval;
float CRenderer::CV_r_envtexupdateinterval;
AllocateConstIntCVar(CRenderer,CV_r_waterreflections);
AllocateConstIntCVar(CRenderer,CV_r_waterreflections_mgpu);
AllocateConstIntCVar(CRenderer,CV_r_waterreflections_quality);
AllocateConstIntCVar(CRenderer,CV_r_waterreflections_use_min_offset);
float CRenderer::CV_r_waterreflections_min_visible_pixels_update;
float CRenderer::CV_r_waterreflections_minvis_updatefactormul;
float CRenderer::CV_r_waterreflections_minvis_updatedistancemul;
int CRenderer::CV_r_watercaustics;
float CRenderer::CV_r_watercausticsdistance;
int CRenderer::CV_r_watercausticsdeferred;
AllocateConstIntCVar(CRenderer,CV_r_water_godrays);
AllocateConstIntCVar(CRenderer,CV_r_water_random_seed);
int CRenderer::CV_r_WaterUpdateThread; 
AllocateConstIntCVar(CRenderer,CV_r_texture_anisotropic_level);
AllocateConstIntCVar(CRenderer,CV_r_texnoaniso);
AllocateConstIntCVar(CRenderer,CV_r_reflections);	
AllocateConstIntCVar(CRenderer,CV_r_reflections_quality);	
float CRenderer::CV_r_waterreflections_offset;	
AllocateConstIntCVar(CRenderer,CV_r_reloadshaders);
AllocateConstIntCVar(CRenderer,CV_r_detailtextures);
float CRenderer::CV_r_detaildistance;
AllocateConstIntCVar(CRenderer,CV_r_texbindmode);
AllocateConstIntCVar(CRenderer,CV_r_nodrawshaders);
int CRenderer::CV_r_nodrawnear;
float CRenderer::CV_r_DrawNearZRange;
float CRenderer::CV_r_DrawNearFarPlane;
float CRenderer::CV_r_drawnearfov;
AllocateConstIntCVar(CRenderer,CV_r_profileshaders);
AllocateConstIntCVar(CRenderer,CV_r_ProfileShadersSmooth);
AllocateConstIntCVar(CRenderer,CV_r_ProfileShadersGroupByName);
ICVar *CRenderer::CV_r_excludeshader;
ICVar *CRenderer::CV_r_excludemesh;

float CRenderer::CV_r_gamma;
float CRenderer::CV_r_contrast;
float CRenderer::CV_r_brightness;

AllocateConstIntCVar(CRenderer,CV_r_nohwgamma);

int	CRenderer::CV_r_scissor;

int CRenderer::CV_r_coronas;
AllocateConstIntCVar(CRenderer,CV_r_coronashafts);
AllocateConstIntCVar(CRenderer,CV_r_LensGhostsForPointLight);
AllocateConstIntCVar(CRenderer,CV_r_LensGhostsForSun);
float CRenderer::CV_r_coronafade;
float CRenderer::CV_r_coronasizescale;
float CRenderer::CV_r_coronacolorscale;

AllocateConstIntCVar(CRenderer,CV_r_wireframe);
int CRenderer::CV_r_GetScreenShot;

AllocateConstIntCVar(CRenderer,CV_r_character_nodeform);

AllocateConstIntCVar(CRenderer,CV_r_VegetationSpritesGenDebug);
AllocateConstIntCVar(CRenderer,CV_r_VegetationSpritesMaxLightingUpdates);
AllocateConstIntCVar(CRenderer,CV_r_ZPassOnly);
AllocateConstIntCVar(CRenderer,CV_r_VegetationSpritesNoGen);
int	CRenderer::CV_r_VegetationSpritesTexRes;
AllocateConstIntCVar(CRenderer,CV_r_VegetationSpritesGenAlways);
AllocateConstIntCVar(CRenderer,CV_r_VegetationAlphaTestOnly);

int CRenderer::CV_r_ShowVideoMemoryStats;

ICVar* CRenderer::CV_r_ShowTexture = NULL;
ICVar* CRenderer::CV_r_TexturesStreamingDebugfilter = NULL;
int CRenderer::CV_r_TexturesStreamingDebugMinSize;
int CRenderer::CV_r_TexturesStreamingDebugMinMip;
AllocateConstIntCVar(CRenderer,CV_r_TexturesStreamingDebugDumpIntoLog);

AllocateConstIntCVar(CRenderer,CV_r_ShowLightBounds);

AllocateConstIntCVar(CRenderer,CV_r_MergeRenderChunks);
AllocateConstIntCVar(CRenderer,CV_r_TextureCompressor);

AllocateConstIntCVar(CRenderer,CV_r_UseGSParticles);

float CRenderer::CV_r_ZFightingDepthScale;
float CRenderer::CV_r_ZFightingExtrude;

AllocateConstIntCVar(CRenderer,CV_r_useSRGB);
float CRenderer::CV_r_TexelsPerMeter;

int CRenderer::CV_r_ConditionalRendering;
AllocateConstIntCVar(CRenderer,CV_r_PS3HalfResRendering);
AllocateConstIntCVar(CRenderer,CV_r_PS3VMemDefrag);
AllocateConstIntCVar(CRenderer,CV_r_PS3VMemDefragDebug);
AllocateConstIntCVar(CRenderer,CV_r_PS3HaltOnPossibleRSXDump);
float CRenderer::CV_r_PS3TextureBias;
float CRenderer::CV_r_PS3TextureOptimization;
int CRenderer::CV_r_PS3TextureAnisoQual;
int CRenderer::CV_r_PS3ConstBufferAdjustment;
int CRenderer::CV_r_PS3SoftwareRasterizer;
int CRenderer::CV_r_PS3GPad;

int CRenderer::CV_r_enableAltTab;
int CRenderer::CV_r_StereoDevice;
int CRenderer::CV_r_StereoMode;
int CRenderer::CV_r_StereoOutput;

int CRenderer::CV_r_StereoFlipEyes;
float CRenderer::CV_r_StereoStrength;
float CRenderer::CV_r_StereoEyeDist;
float CRenderer::CV_r_StereoScreenDist;
float CRenderer::CV_r_StereoNearGeoScale;
float CRenderer::CV_r_StereoHudScreenDist;
float CRenderer::CV_r_StereoGammaAdjustment;
int CRenderer::CV_r_ConsoleBackbufferWidth;
int CRenderer::CV_r_ConsoleBackbufferHeight;

int CRenderer::CV_r_CustomResMaxSize;
int CRenderer::CV_r_CustomResWidth;
int CRenderer::CV_r_CustomResHeight;
int CRenderer::CV_r_CustomResPreview;
int CRenderer::CV_r_Supersampling;
int CRenderer::CV_r_SupersamplingFilter;

float CRenderer::CV_r_FogDepthTest;
#if defined(VOLUMETRIC_FOG_SHADOWS)
int CRenderer::CV_r_FogShadows;
#endif

AllocateConstIntCVar(CRenderer,CV_r_Scratches);
AllocateConstIntCVar(CRenderer,CV_r_HUDHitEffect);
AllocateConstIntCVar(CRenderer,CV_r_RainDropsEffect);

AllocateConstIntCVar(CRenderer,CV_r_RefractionPartialResolves);

AllocateConstIntCVar(CRenderer,CV_r_Batching);

float CRenderer::CV_r_FlashMatTexResQuality;

int CRenderer::CV_r_DynTexSourceSharedRTWidth;
int CRenderer::CV_r_DynTexSourceSharedRTHeight;
int CRenderer::CV_r_DynTexSourceUseSharedRT;

#if !defined(_RELEASE)
int CRenderer::CV_r_PS3AllocFailureResource;
int CRenderer::CV_r_PS3AllocFailureRate;
#endif

#if defined(ENABLE_RENDER_AUX_GEOM)
int CRenderer::CV_r_enableauxgeom;
#endif

//////////////////////////////////////////////////////////////////////

#if !defined (XENON) && !defined(PS3) && !defined(CAFE) && !defined(NULL_RENDERER)

static void ShadersPrecache (IConsoleCmdArgs* Cmd)
{
  gRenDev->m_cEF.mfPrecacheShaders(false, false);
}
static void ShadersStats (IConsoleCmdArgs* Cmd)
{
  gRenDev->m_cEF.mfPrecacheShaders(false, true);
}
static void ShadersPrecacheLevels (IConsoleCmdArgs* Cmd)
{
  gRenDev->m_cEF.mfPrecacheShadersLevels();
}

static void ShadersPrecacheList (IConsoleCmdArgs* Cmd)
{
  gRenDev->m_cEF.mfPrecacheShaders(true, false);
}
static void ShadersStatsList (IConsoleCmdArgs* Cmd)
{
  gRenDev->m_cEF.mfPrecacheShaders(true, true);
}

static void ShadersOptimise (IConsoleCmdArgs* Cmd)
{
  uint32 nComp = CRenderer::CV_r_shadersintcompiler;
  if (CRenderer::CV_r_shadersxenon)
  {
    CRenderer::CV_r_shadersintcompiler = 0;

    CParserBin::SetupForXenon();
    CryLogAlways("\nStarting shaders optimizing for X360...");
    string str = string("%USER%/") + string(gRenDev->m_cEF.m_ShadersCache);
    iLog->Log("Optimize user folder: '%s'", gRenDev->m_cEF.m_ShadersCache);
    gRenDev->m_cEF.mfOptimiseShaders(str.c_str(), false);
  }
  if (CRenderer::CV_r_shadersps3)
  {
    CRenderer::CV_r_shadersintcompiler = 0;

    CParserBin::SetupForPS3();
    CryLogAlways("\nStarting shaders optimizing for PS3...");
    string str = string("%USER%/") + string(gRenDev->m_cEF.m_ShadersCache);
    iLog->Log("Optimize user folder: '%s'", gRenDev->m_cEF.m_ShadersCache);
    gRenDev->m_cEF.mfOptimiseShaders(str.c_str(), false);
  }
  if (CRenderer::CV_r_shadersdx9)
  {
    CRenderer::CV_r_shadersintcompiler = 1;

    CParserBin::SetupForD3D9();
    CryLogAlways("\nStarting shaders optimizing for DX9...");
    string str = string("%USER%/") + string(gRenDev->m_cEF.m_ShadersCache);
    iLog->Log("Optimize user folder: '%s'", gRenDev->m_cEF.m_ShadersCache);
    gRenDev->m_cEF.mfOptimiseShaders(str.c_str(), false);
  }
  if (CRenderer::CV_r_shadersdx11)
  {
    CRenderer::CV_r_shadersintcompiler = 0;

    CParserBin::SetupForD3D10();
    CryLogAlways("\nStarting shaders optimizing for DX11...");
    string str = string("%USER%/") + string(gRenDev->m_cEF.m_ShadersCache);
    iLog->Log("Optimize user folder: '%s'", gRenDev->m_cEF.m_ShadersCache);
    gRenDev->m_cEF.mfOptimiseShaders(str.c_str(), false);
  }
  CRenderer::CV_r_shadersintcompiler = nComp;



#if defined (DIRECT3D10)
  CParserBin::SetupForD3D10();


#elif defined (DIRECT3D9)
  CParserBin::SetupForD3D9();


#endif
}

static void ShadersMerge (IConsoleCmdArgs* Cmd)
{
  gRenDev->m_cEF.mfMergeShaders();
}
#endif

static const char *showRenderTargetHelp = 
	"Displays render targets - for debug purpose\n"
	"[Usage]\n"
	"r_ShowRenderTarget -l : list all available render targets\n"
	"r_ShowRenderTarget -l hdr : list all available render targets whose name contain 'hdr'\n"
	"r_ShowRenderTarget -nf zpass : show any render targets whose name contain 'zpass' with no filtering in 2x2(default) table\n"
	"r_ShowRenderTarget -c:3 pass : show any render targets whose name contain 'pass' in 3x3 table\n"
	"r_ShowRenderTarget z hdr : show any render targets whose name contain either 'z' or 'hdr'\n"
	"r_ShowRenderTarget scene:rg scene:b : show any render targets whose name contain 'scene' first with red-green channels only and then with a blue channel only\n"
	"r_ShowRenderTarget scenetarget:rgba:2 : show any render targets whose name contain 'scenetarget' with all channels multiplied by 2\n"
	"r_ShowRenderTarget scene:b hdr:a : show any render targets whose name contain 'scene' with a blue channel only and ones whose name contain 'hdr' with an alpha channel only";

void CRenderer::Cmd_ShowRenderTarget( IConsoleCmdArgs* pArgs )
{
	int argCount = pArgs->GetArgCount();

	gRenDev->m_showRenderTargetInfo.Reset();

	if (argCount <= 1)
	{
		string help = showRenderTargetHelp;
		int curPos = 0;
		string line = help.Tokenize("\n", curPos);
		while (false == line.empty())
		{
			gEnv->pLog->Log(line);
			line = help.Tokenize("\n", curPos);
		}
		return;
	}

	// Check for '-l'.
	for (int i=1; i<argCount; ++i)
	{
		if (strcmp(pArgs->GetArg(i), "-l") == 0)
		{
			gRenDev->m_showRenderTargetInfo.bShowList = true;
			break;
		}
	}

	// Check for '-c:*'.
	for (int i=1; i<argCount; ++i)
	{
		if (strlen(pArgs->GetArg(i)) > 3 && strncmp(pArgs->GetArg(i), "-c:", 3) == 0)
		{
			gRenDev->m_showRenderTargetInfo.col = atoi(pArgs->GetArg(i)+3);
			if (gRenDev->m_showRenderTargetInfo.col <= 0)
				gRenDev->m_showRenderTargetInfo.col = 2;
		}
	}

	// Now gather all render targets.
	std::vector<CTexture*> allRTs;
	SResourceContainer *pRL = CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
	ResourcesMapItor it;
	for (it=pRL->m_RMap.begin(); it!=pRL->m_RMap.end(); ++it)
	{
		CTexture *tp = (CTexture *)it->second;
		if (tp && !tp->IsNoTexture())
		{
			if ((tp->GetFlags() & (FT_USAGE_RENDERTARGET | FT_USAGE_DYNAMIC)) && tp->GetDevTexture())
				allRTs.push_back(tp);
		}
	}

	// Process actual arguments with possible '-nf', '-f' options.
	bool bNoRegularArgs = true;
	for (int i=1; i<argCount; ++i)
	{
		const char *pCurArg = pArgs->GetArg(i);

		bool bColOption = strlen(pCurArg) > 3 && strncmp(pCurArg, "-c:", 3) == 0;
		if (strcmp(pCurArg, "-l") == 0 || bColOption)
			continue;

		bool bFiltered = true;
		if (strcmp(pCurArg, "-nf") == 0)
		{
			bFiltered = false;
		}
		else if (strcmp(pCurArg, "-f") == 0)
		{
			bFiltered = true;
		}
		else
		{
			bNoRegularArgs = false;
			string argTxt = pCurArg, nameTxt, channelTxt, mulTxt;
			argTxt.MakeLower();
			float multiplier = 1.0f;
			size_t pos = argTxt.find(':');
			if (pos == string::npos)
			{
				nameTxt = argTxt;
				channelTxt = "rgba";
			}
			else
			{
				nameTxt = argTxt.substr(0, pos);
				channelTxt = argTxt.substr(pos+1, string::npos);
				pos = channelTxt.find(':');
				if (pos != string::npos)
				{
					mulTxt = channelTxt.substr(pos+1, string::npos);
					multiplier = static_cast<float>(atof(mulTxt.c_str()));
					if (multiplier <= 0)
						multiplier = 1.0f;
				}
			}

			Vec4 channelWeight(0,0,0,0);
			if (channelTxt.find('r') != string::npos)
				channelWeight.x = 1.0f;
			if (channelTxt.find('g') != string::npos)
				channelWeight.y = 1.0f;
			if (channelTxt.find('b') != string::npos)
				channelWeight.z = 1.0f;
			if (channelTxt.find('a') != string::npos)
				channelWeight.w = 1.0f;

			channelWeight *= multiplier;

      int nFound = -1;
			for (size_t k=0; k<allRTs.size(); ++k)
			{
				string texName = allRTs[k]->GetName();
				texName.MakeLower();
				if (!strcmp(texName.c_str(), nameTxt.c_str()))
				{
          nFound = k;
					SShowRenderTargetInfo::RT rt;
					rt.bFiltered = bFiltered;
					rt.pTexture = allRTs[k];
					rt.channelWeight = channelWeight;
					gRenDev->m_showRenderTargetInfo.rtList.push_back(rt);
				}
			}
			for (size_t k=0; k<allRTs.size(); ++k)
			{
        if (k == nFound)
          continue;
				string texName = allRTs[k]->GetName();
				texName.MakeLower();
				if (texName.find(nameTxt.c_str()) != string::npos)
				{
					SShowRenderTargetInfo::RT rt;
					rt.bFiltered = bFiltered;
					rt.pTexture = allRTs[k];
					rt.channelWeight = channelWeight;
					gRenDev->m_showRenderTargetInfo.rtList.push_back(rt);
				}
			}
		}
	}

	if (bNoRegularArgs && gRenDev->m_showRenderTargetInfo.bShowList) // This means showing all items.
	{
		for (size_t k=0; k<allRTs.size(); ++k)
		{
			SShowRenderTargetInfo::RT rt;
			rt.bFiltered = true; // Doesn't matter, actually.
			rt.pTexture = allRTs[k];
			gRenDev->m_showRenderTargetInfo.rtList.push_back(rt);
		}
	}
}

static void cmd_OverscanBorders( IConsoleCmdArgs *pParams )
{
	int argCount = pParams->GetArgCount();

	if (argCount > 1)
	{
		CRenderer::s_overscanBorders.x = clamp_tpl((float)atof(pParams->GetArg(1)), 0.0f, 25.0f) * 0.01f;

		if (argCount > 2)
		{
			CRenderer::s_overscanBorders.y = clamp_tpl((float)atof(pParams->GetArg(2)), 0.0f, 25.0f) * 0.01f;
		}
		else
		{
			CRenderer::s_overscanBorders.y = CRenderer::s_overscanBorders.x;
		}
	}
	else
	{
#if !defined(__SPU__)
		gEnv->pLog->LogWithType(ILog::eInputResponse,"Overscan Borders: Left/Right %G %% , Top/Bottom %G %%",
			CRenderer::s_overscanBorders.x*100.0f, CRenderer::s_overscanBorders.y*100.0f);
#endif
	}
}


static void OnChange_CV_r_HDRRendering( ICVar* pCVar )
{
	ITimeOfDay* pTimeOfDay( gEnv->p3DEngine->GetTimeOfDay() );
	float time( pTimeOfDay->GetTime() );
	pTimeOfDay->SetTime( time, true );

	// MSAA requires HDR mode on
	// search for #LABEL_MSAA_HDR
	if(!pCVar->GetIVal())
	{
		// HDR was switched off
		ICVar *pMSAA = gEnv->pConsole->GetCVar("r_MSAA");

		if(pMSAA->GetIVal())
			pMSAA->Set(0);			// switch off MSAA
	}
}

static void OnChange_CV_r_TexelsPerMeter(ICVar* /*pCVar*/)
{
	ICVar* pCV_e_sketch_mode = gEnv->pConsole->GetCVar("e_sketch_mode");
	if (pCV_e_sketch_mode)
		pCV_e_sketch_mode->Set(CRenderer::CV_r_TexelsPerMeter > 0.0f ? 4 : 0);
}

static void GetLogVBuffersStatic(ICVar* pCVar )
{
	gRenDev->GetLogVBuffers();
}

void CRenderer::ChangeGeomInstancingThreshold( ICVar *pVar )
{
	// get user value
	m_iGeomInstancingThreshold = CV_r_geominstancingthreshold;

	// auto
	if(m_iGeomInstancingThreshold<0)
	{







		int nGPU = gRenDev->GetFeatures() & RFT_HW_MASK;

		if(nGPU==RFT_HW_ATI)
			CRenderer::m_iGeomInstancingThreshold = 2;				// seems to help in performance on all cards
		 else
     if (nGPU == RFT_HW_NVIDIA)
			CRenderer::m_iGeomInstancingThreshold = 8;				//
		 else
			CRenderer::m_iGeomInstancingThreshold = 7;				// might be a good start - can be tweaked further

	}
	
	CryLogAlways("used GeomInstancingThreshold is %d",m_iGeomInstancingThreshold);
}





CRenderer::CRenderer()
{}

void CRenderer::InitRenderer()
{ 
	if (!gRenDev)
    gRenDev = this;
  m_cEF.m_Bin.m_pCEF = &m_cEF;

	m_pIntroMovieRenderer = 0;

	m_bShaderCacheGen = false;
	m_bSystemResourcesInit = 0;

	m_bSystemTargetsInit = 0;
  m_bIsWindowActive = true;

	m_bShadowsEnabled = true;
	m_bCloudShadowsEnabled = true;

#if defined(VOLUMETRIC_FOG_SHADOWS)
	m_bVolFogShadowsEnabled = false;
	m_bVolFogCloudShadowsEnabled = false;
#endif

  m_nCurMinAniso = 1;
  m_nCurMaxAniso = 16;
  m_wireframe_mode = R_SOLID_MODE;
  m_wireframe_mode_prev = R_SOLID_MODE;
  m_RP.m_StateOr = 0;
  m_RP.m_StateAnd = -1;

	m_pSpriteVerts = NULL;
	m_pSpriteInds = NULL;

  DefineConstIntCVar3("r_DeferredShadingLightVolumes", CV_r_deferredshadingLightVolumes, 1, VF_DUMPTODISK,
    "Toggles Light volumes for deferred shading.\n"
    "Usage: r_DeferredShadingLightVolumes [0/1]\n"
    "Default is 1 (enabled)");

  DefineConstIntCVar3("r_DeferredDecals", CV_r_deferredDecals, 3, VF_DUMPTODISK,
    "Toggles deferred decals.\n"
    "Usage: r_DeferredDecals [0/1]\n"
    "Default is 1 (general pass darken), 2 (light buffer darken), 3 (alpha blended), 0 Disables. ");

  DefineConstIntCVar3("r_deferredDecalsDebug", CV_r_deferredDecalsDebug, 0, VF_DUMPTODISK,
    "Display decals debug info.\n"
    "Usage: r_deferredDecalsDebug [0/1]");

	DefineConstIntCVar3("r_DeferredShadingEnvProbes", CV_r_DeferredShadingEnvProbes, 1, VF_DUMPTODISK,
		"Toggles deferred environment probes rendering.\n"
		"Usage: r_DeferredShadingEnvProbes [0/1]\n"
		"Default is 1 (enabled)");

	DefineConstIntCVar3("r_DeferredShadingHeightBasedAmbient", CV_r_DeferredShadingHeightBasedAmbient, 1, VF_NULL,
		"Toggles experimental height based ambient.\n"
		"Usage: r_DeferredShadingHeightBasedAmbient [0/1]\n"
		"Default is 1 (enabled)");

  DefineConstIntCVar3("r_DeferredShadingStencilPrepass", CV_r_DeferredShadingStencilPrepass, 1, VF_DUMPTODISK,
    "Toggles deferred shading stencil pre pass.\n"
    "Usage: r_DeferredShadingStencilPrepass [0/1]\n"
    "Default is 1 (enabled)");

  DefineConstIntCVar3("r_DeferredShadingScissor", CV_r_DeferredShadingScissor, 1, VF_DUMPTODISK,
    "Toggles deferred shading scissor test.\n"
    "Usage: r_DeferredShadingScissor [0/1]\n"
    "Default is 1 (enabled)");

  DefineConstIntCVar3("r_DeferredShadingDepthBoundsTest", CV_r_DeferredShadingDepthBoundsTest, DEF_SHAD_DBT_DEFAULT_VAL, 
    VF_DUMPTODISK,
    "Toggles deferred shading depth bounds test.\n"
    "Usage: r_DeferredShadingDepthBoundsTest [0/1]\n"
    "Default is 1 (enabled)");

  DefineConstIntCVar3("r_DeferredShadingDBTstencil", CV_r_deferredshadingDBTstencil, DEF_SHAD_DBT_STENCIL_DEFAULT_VAL, 
    VF_DUMPTODISK,
    "Toggles deferred shading combined depth bounds test + stencil test.\n"
    "Usage: r_DeferredShadingDBTstencil [0/1]\n"
    "Default is 1 (enabled)");

  DefineConstIntCVar3("r_DeferredShadingDebug", CV_r_DeferredShadingDebug, 0, VF_DUMPTODISK,
    "Toggles deferred shading debug.\n"
    "Usage: r_DeferredShadingDebug [0/1]\n"
    "  0 disabled (Default)\n"
    "  1: Visualize g-buffer and l-buffers\n"
    "  2: Debug deferred lighting fillrate (brighter colors means more expensive)\n");

  DefineConstIntCVar3("r_DeferredShadingLights", CV_r_DeferredShadingLights, 1, VF_DUMPTODISK,
    "Enables/Disables lights processing.\n"
    "Usage: r_DeferredShadingLights [0/1]\n"
    "Default is 1 (enabled)");

  DefineConstIntCVar3("r_DeferredShadingAmbient", CV_r_DeferredShadingAmbient, 1, VF_DUMPTODISK,
    "Enables/Disables ambient processing.\n"
    "Usage: r_DeferredShadingAmbient [0/1/2]\n"
    "  0: no ambient passes (disabled)\n"
    "  1: vis areas and outdoor ambient  (default)\n"
    "  2: only outdoor (debug vis areas mode)\n");

  REGISTER_CVAR3("r_DeferredShadingLightLodRatio", CV_r_DeferredShadingLightLodRatio, 1.0f, VF_DUMPTODISK,
    "Sets deferred shading light intensity threshold for PS3.\n"
    "Usage: r_DeferredShadingLightLodRatio [value]\n"
    "Default is 0.1");

	REGISTER_CVAR3("r_DeferredShadingLightStencilRatio", CV_r_DeferredShadingLightStencilRatio, 0.21f, VF_DUMPTODISK,
		"Sets screen ratio for deferred lights to use stencil (eg: 0.2 - 20% of screen).\n"
		"Usage: r_DeferredShadingLightStencilRatio [value]\n"
		"Default is 0.2");
  







	REGISTER_CVAR3("r_DeferredShadingSortLights", CV_r_DeferredShadingSortLights, 0, VF_CHEAT,
		"Sorts light by influence\n"
		"Usage: r_DeferredShadingSortLights [0/1]\n"
		"Default is 0 (off)");
	
	DefineConstIntCVar3("r_LightPropagationVolumes", CV_r_LightPropagationVolumes, 1, VF_CHEAT,
		"Toggles Light Propagation Volumes.\n"
		"Usage: r_LightPropagationVolumes [0/1]\n"
		"Default is 1 (on)");

#ifdef USE_HDR

  ICVar* pCV_r_HDRRendering = 

		REGISTER_CVAR3("r_HDRRendering", CV_r_HDRRendering, 1, VF_DUMPTODISK,
		"Toggles HDR rendering.\n"
		"Usage: r_HDRRendering [0/1]\n"
		"Default is 1 (on), film curve tone mapping. \n"
		"Set to 0 to disable HDR rendering.");
	pCV_r_HDRRendering->SetOnChangeCallback( OnChange_CV_r_HDRRendering );
  DefineConstIntCVar3("r_HDRDebug", CV_r_HDRDebug, 0, VF_NULL,
		"Toggles HDR debugging info (to debug HDR/eye adaptation)\n"
    "Usage: r_HDRDebug\n"
		"0 off (default)\n"
		"1 show gamma-corrected scene target without HDR processing\n"
		"2 identify illegal colors (grey=normal, red=NotANumber, green=negative)\n"
		"3 display internal HDR textures\n"
		"4 display HDR range adaptation\n"
		"5 debug merged posts composition mask\n");

#endif
  
	REGISTER_CVAR3("r_HDRLevel", CV_r_HDRLevel, 8.0f, VF_DUMPTODISK,
		"HDR rendering range level (color multiplier tweak together with hdr offset)\n"
    "Usage: r_HDRLevel [Value]\n"
    "Default is 6.0f");

	REGISTER_CVAR3("r_HDROffset", CV_r_HDROffset, 10.0f, VF_DUMPTODISK,
		"HDR rendering range offset (color multiplier tweak together with hdr level)\n"
		"Usage: r_HDROffset [Value]\n"
		"Default is 10.0f");

	DefineConstIntCVar3("r_HDRVignetting", CV_r_HDRVignetting, 1, VF_DUMPTODISK,
		"HDR viggneting\n"
		"Usage: r_HDRVignetting [Value]\n"
		"Default is 1 (enabled)");

	DefineConstIntCVar3("r_HDRRangeAdapt", CV_r_HDRRangeAdapt, HDR_RANGE_ADAPT_DEFAULT_VAL, VF_DUMPTODISK,
		"Enable/Disable HDR range adaptation (improve precision - minimize banding) \n"
		"Usage: r_HDRRangeAdapt [Value]\n"
		"Default is 1");

	REGISTER_CVAR3("r_HDREyeAdaptionCache", CV_r_HDREyeAdaptionCache, 4, VF_DUMPTODISK,
		"Enable/Disable eye adaptation caching overframes\n"
		"Usage: r_HDREyeAdaptionCache [value]\n"
		"Default is 4. 0 - always update, 1 - every other frame, 2 - every two frames, etc");	

	REGISTER_CVAR3("r_HDRRangeAdaptMax", CV_r_HDRRangeAdaptMax, 1.0f, VF_DUMPTODISK,
		"Set HDR range adaptation max adaptation (improve precision - minimize banding) \n"
		"Usage: r_HDRRangeAdaptMax [Value]\n"
		"Default is 1.0f");	

	REGISTER_CVAR3("r_HDRRangeAdaptMaxRange", CV_r_HDRRangeAdaptMaxRange, 4.0f, VF_DUMPTODISK,
		"Set HDR range adaptation max adaptation (improve precision - minimize banding) \n"
		"Usage: r_HDRRangeAdaptMaxRange [Value]\n"
		"Default is 4.0f");	

	REGISTER_CVAR3("r_HDRRangeAdaptLBufferMax", CV_r_HDRRangeAdaptLBufferMax, 0.125f, VF_DUMPTODISK,
		"Set range adaptation max adaptation for light buffers (improve precision - minimize banding) \n"
		"Usage: r_HDRRangeAdaptLBufferMax [Value]\n"
		"Default is 0.25f");	

	REGISTER_CVAR3("r_HDRRangeAdaptLBufferMaxRange", CV_r_HDRRangeAdaptLBufferMaxRange, 2.0f, VF_DUMPTODISK,
		"Set range adaptation max range adaptation for light buffers (improve precision - minimize banding) \n"
		"Usage: r_HDRRangeAdaptLBufferMaxRange [Value]\n"
		"Default is 2.0f");	


	DefineConstIntCVar3("r_HDRTexFormat", CV_r_HDRTexFormat, 0, VF_DUMPTODISK,
		"HDR texture format. \n"
		"Usage: r_HDRTexFormat [Value] 0:(low precision - cheaper/faster), 1:(high precision)\n"
		"Default is 0");

	DefineConstIntCVar3("r_HDRForceUpdateTextures", CV_r_HDRForceUpdateTextures, 0, VF_DUMPTODISK,
		"Forces updating HDR textures. \n");

	// Eye Adaption
	REGISTER_CVAR3("r_EyeAdaptationFactor", CV_r_HDREyeAdaptationFactor, 0.85f, VF_DUMPTODISK,
		"HDR rendering eye adaptation factor (0 means no adaption to current scene luminance, 1 means full adaption)\n"
		"Usage: r_HDREyeAdaptionFactor [Value]\n"
		"Default is 0.85");
	REGISTER_CVAR3("r_EyeAdaptationBase", CV_r_HDREyeAdaptationBase, EYEADAPTIONBASEDEFAULT, VF_NULL,
		"HDR rendering eye adaptation base value (smaller values result in brighter adaption)\n"
		"Usage: r_EyeAdaptationBase [Value]");
	REGISTER_CVAR3("r_EyeAdaptationSpeed", CV_r_HDREyeAdaptationSpeed, 2.0f, VF_NULL,
		"HDR rendering eye adaptation speed\n"
		"Usage: r_EyeAdaptationSpeed [Value]");
	REGISTER_CVAR3("r_EyeAdaptationLocal", CV_r_HDREyeAdaptationLocal, 0, VF_NULL,
		"HDR rendering eye adaptation local\n"
		"Usage: 0==off 1==4x4 2==16x16 3==256x256");


	REGISTER_CVAR3("r_HDRRangeAdaptationSpeed", CV_r_HDRRangeAdaptationSpeed, 4.0f, VF_NULL,
		"HDR range adaption speed\n"
		"Usage: r_HDRRangeAdaptationSpeed [Value]");

	REGISTER_CVAR3("r_HDRGrainAmount", CV_r_HDRGrainAmount, 0.6f, VF_NULL,
		"HDR camera grain amount\n"
		"Usage: r_HDRGrainAmount [Value]");

	REGISTER_CVAR3("r_HDRBloomMul", CV_r_HDRBloomMul, 0.8f, VF_NULL,
		"HDR bloom multiplier\n"
		"Usage: r_HDRBloomMul [Value]");

	
  REGISTER_CVAR3("r_HDRBrightThreshold", CV_r_HDRBrightThreshold, 8.0f, VF_DUMPTODISK,
		"HDR rendering bright threshold.\n"
		"Usage: r_HDRBrightThreshold [Value]\n"
		"Default is 8.0");
  REGISTER_CVAR3("r_HDRBrightOffset", CV_r_HDRBrightOffset, 8.0f, VF_DUMPTODISK,
		"HDR rendering bright offset.\n"
		"Usage: r_HDRBrightOffset [Value]\n"
		"Default is 8.0");
	REGISTER_CVAR3("r_HDRBrightLevel", CV_r_HDRBrightLevel, 1.25f, VF_DUMPTODISK,
		"HDR rendering level (bloom multiplier, tweak together with threshold)\n"
		"Usage: r_HDRBrightLevel [Value]\n"
		"Default is 1.25");

	REGISTER_CVAR3("r_HDRSCurveMin", CV_r_HDRSCurveMin, 0.0f, VF_DUMPTODISK,
		"HDR s-curve min output\n"
		"Usage: r_HDRSCurveMin [Value]\n"
		"Default is 0.0");

	REGISTER_CVAR3("r_HDRSCurveMax", CV_r_HDRSCurveMax, 0.95f, VF_DUMPTODISK,
		"HDR s-curve max output\n"
		"Usage: r_HDRSCurveMax [Value]\n"
		"Default is 0.95");

	REGISTER_CVAR3("r_HDRSaturation", CV_r_HDRSaturation, 0.875f, VF_DUMPTODISK,
		"HDR saturation\n"
		"Usage: r_HDRSaturation [Value]\n"
		"Default is 1.0");

	REGISTER_CVAR3("r_HDRBrightness", CV_r_HDRBrightness, 1.0f, VF_DUMPTODISK,
		"HDR brightness\n"
		"Usage: r_HDRBrightness [Value]\n"
		"Default is 1.0");

	REGISTER_CVAR3("r_HDRBlueShift", CV_r_HDRBlueShift, 0.0f, VF_DUMPTODISK,
		"HDR rendering blue shift.\n"
		"Usage: r_HDRBlueShift 0 to 1\n"
		"Default is 0 (disabled). Set to 1 to use max blue shift strength");

  REGISTER_CVAR3("r_Beams", CV_r_beams, 3, VF_NULL,
    "Toggles light beams.\n"
    "Usage: r_Beams [0/1/2/3]\n"
    "Default is 3 (optimized beams with glow support). Set to 0 to disable beams or 2 to\n"
		"use fake beams. Set 1 for real beams, full resolution (slower). Set to 3 to use\n"
		"optimized and with glow support beams.");
#if defined(DIRECT3D10)
  REGISTER_CVAR3("r_BeamsSoftClip", CV_r_beamssoftclip, 1, VF_NULL,
    "Toggles light beams clip type.\n"
    "Usage: r_BeamsSoftClip [0/1]\n"
    "Default is 1 (software clip beams). Set to 0 to enable hardware clipping.");
#else
  REGISTER_CVAR3("r_BeamsSoftClip", CV_r_beamssoftclip, 1, VF_NULL,
    "Toggles light beams clip type.\n"
    "Usage: r_BeamsSoftClip [0/1]\n"
    "Default is 1 (software clip beams). Set to 0 to enable hardware clipping.");
#endif
  REGISTER_CVAR3("r_BeamsHelpers", CV_r_beamshelpers, 0, VF_NULL,
    "Toggles light beams helpers drawing.\n"
    "Usage: r_BeamsHelpers [0/1]\n"
    "Default is 0 (disabled helpers). Set to 1 to enable drawing helpers.");
  REGISTER_CVAR3("r_BeamsMaxSlices", CV_r_beamsmaxslices, 200, VF_NULL,
    "Number of volumetric slices allowed per light beam.\n"
    "Usage: r_BeamsMaxSlices [1-300]\n"
    "Default is 200 (high-spec).");
  REGISTER_CVAR3("r_BeamsDistFactor", CV_r_beamsdistfactor, 0.01f, VF_NULL,
    "Distance between slices.\n"
    "Usage: r_BeamsDistFactor [fValue]\n"
    "Default is 0.01 (0.01 meters between slices).");
  ICVar *pCVar_GeomInst = REGISTER_CVAR3("r_GeomInstancingThreshold", CV_r_geominstancingthreshold, -1, VF_NULL,
    "If the instance count gets bigger than the specified value the instancing feature is used.\n"
    "Usage: r_GeomInstancingThreshold [Num]\n"
    "Default is -1 (automatic depending on hardware, used value can be found in the log)");
	pCVar_GeomInst->SetOnChangeCallback(ChangeGeomInstancingThreshold);

  REGISTER_CVAR3("r_BatchType", CV_r_batchtype, 2, VF_NULL,
    "0 - CPU friendly.\n"
    "1 - GPU friendly.\n"
    "2 - Automatic.\n");

#ifdef TESSELLATION_RENDERER
	REGISTER_CVAR3("r_WaterTessellationHW", CV_r_WaterTessellationHW, 0, VF_NULL,
		"Enables hw water tessellation.\n"
		"Usage: r_WaterTessellationHW [0/1]");
#endif

  REGISTER_CVAR3("r_TessellationDebug", CV_r_tessellationdebug, 0, VF_NULL,
    "1 - Factor visualizing.\n"
    "Default is 0");
  REGISTER_CVAR3("r_TessellationTriangleSize", CV_r_tessellationtrianglesize, 8.0f, VF_NULL,
    "Desired triangle size for screen-space tessellation.\n"
    "Default is 10.");
  REGISTER_CVAR3("r_DisplacementFactor", CV_r_displacementfactor, 0.2f, VF_NULL,
    "Global displacement amount.\n"
    "Default is 0.4f.");

  DefineConstIntCVar3("r_GeomInstancing", CV_r_geominstancing, GEOM_INSTANCING_DEFAULT_VAL, VF_NULL,
		"Toggles HW geometry instancing.\n"
		"Usage: r_GeomInstancing [0/1]\n"
		"Default is 1 (on). Set to 0 to disable geom. instancing.");

  DefineConstIntCVar3("r_GeomInstancingDebug", CV_r_geominstancingdebug, 0, VF_NULL,
		"Toggles HW geometry instancing debug display.\n"
		"Usage: r_GeomInstancingDebug [0/1/2]\n"
		"Default is 0 (off). Set to 1 to add GPU markers around instanced objects. 2 will visually highlight them as well.");

  DefineConstIntCVar3("r_MaterialsBatching", CV_r_materialsbatching, 1, VF_NULL,
    "Toggles materials batching.\n"
    "Usage: r_MaterialsBatching [0/1]\n"
    "Default is 1 (on). Set to 0 to disable.");

	DefineConstIntCVar3("r_ImpostersDraw", CV_r_impostersdraw, 1, VF_NULL,
    "Toggles imposters drawing.\n"
    "Usage: r_ImpostersDraw [0/1]\n"
    "Default is 1 (on). Set to 0 to disable imposters.");
	REGISTER_CVAR3("r_ImposterRatio", CV_r_imposterratio, 1, VF_NULL,
		"Allows to scale the texture resolution of imposters (clouds)\n"
		"Usage: r_ImposterRatio [1..]\n"
		"Default is 1 (1:1 normal). Bigger values can help to save texture space\n"
		"(e.g. value 2 results in 1/4 texture memory usage)");
  REGISTER_CVAR3("r_ImpostersUpdatePerFrame", CV_r_impostersupdateperframe, 6000, VF_NULL,
    "How many kilobytes to update per-frame.\n"
    "Usage: r_ImpostersUpdatePerFrame [1000-30000]\n"
    "Default is 6000 (6 megabytes)");


























  REGISTER_CVAR3("r_CBStatic", CV_r_CBStatic, 0, VF_NULL,
    "Toggles per-instance CBs as static.\n"
    "Usage: r_UseCBStatic [0/1]\n"
    "Default is 1 (on). Set to 0 to use dynamic update of CB's per-instance.");

  DefineConstIntCVar3("r_CBStaticDebug", CV_r_CBStaticDebug, 0, VF_NULL,
    "Toggles debugging of per-instance CBs.\n"
    "Usage: r_UseCBStaticDebug [0/1]\n"
    "Default is 0 (off). Set to 1 to enable asserts when static CB content is differ from the actual instance content.");
		
	DefineConstIntCVar3("r_ZPassDepthSorting", CV_r_ZPassDepthSorting, ZPASS_DEPTH_SORT_DEFAULT_VAL, VF_NULL,
		"Toggles Z pass depth sorting.\n"
		"Usage: r_ZPassDepthSorting [0/1/2]\n"
		"0: No depth sorting\n"
		"1: Sort by depth layers (default)\n"
		"2: Sort by distance\n");

  REGISTER_CVAR3("r_UseZPass", CV_r_usezpass, 1, VF_NULL,
    "Toggles Z pass.\n"
    "Usage: r_UseZPass [0/1]\n"
    "Default is 1 (on). Set to 0 to disable Z-pass.");
	DefineConstIntCVar3("r_UseAlphaBlend", CV_r_usealphablend, 1, VF_NULL,
		"Toggles alpha blended objects.\n"
		"Usage: r_UseAlphaBlend [0/1]\n"
		"Default is 1 (on). Set to 0 to disable all alpha blended object.");

	DefineConstIntCVar3("r_SoftAlphaTest", CV_r_SoftAlphaTest, 1, VF_NULL,
		"Toggles post processed soft alpha test for shaders supporting this\n"
		"Usage: r_SoftAlphaTest [0/1]\n"
		"Default is 1 (enabled)\n");

  DefineConstIntCVar3("r_UseHWSkinning", CV_r_usehwskinning, 1, VF_NULL,
    "Toggles HW skinning.\n"
    "Usage: r_UseHWSkinning [0/1]\n"
    "Default is 1 (on). Set to 0 to disable HW-skinning.");
  DefineConstIntCVar3("r_UseMaterialLayers", CV_r_usemateriallayers, 2,VF_NULL,
    "Enables material layers rendering.\n"
    "Usage: r_UseMaterialLayers [0/1/2]\n"
    "Default is 2 (optimized). Set to 1 for enabling but with optimization disabled (for debug).");

  DefineConstIntCVar3("r_UseSoftParticles", CV_r_usesoftparticles, 1,VF_NULL,
    "Enables soft particles.\n"
    "Usage: r_UseSoftParticles [0/1]");

  DefineConstIntCVar3("r_UseParticlesRefraction", CV_r_useparticles_refraction, 1,VF_NULL,
    "Enables refractive particles.\n"
    "Usage: r_UseParticlesRefraction [0/1]");

  DefineConstIntCVar3("r_UseParticlesGlow", CV_r_useparticles_glow, 1,VF_NULL,
    "Enables glow particles.\n"
    "Usage: r_UseParticlesGlow [0/1]");

	DefineConstIntCVar3("r_UseParticlesMerging", CV_r_useparticles_merge, 0,VF_NULL,
		"Enables merging of particles drawcalls.\n"
		"Usage: CV_r_useparticles_merge [0/1]");

	DefineConstIntCVar3("r_UseParticlesHalfRes", CV_r_useparticles_halfres, 0,VF_NULL,
		"Enables rendering of particles of specified blend operation in half resolution.\n"
		"Usage: r_UseParticlesHalfRes [0:off/1:additive/2:alpha]");

	DefineConstIntCVar3("r_UseParticlesHalfResForce", CV_r_useparticles_halfres_force, 0,VF_NULL,
		"Forces all particles of specified blend operation to be rendered in half resolution, regardless of param setting.\n"
		"Usage: r_UseParticlesHalfResForce [0:normal/1:force]");

	DefineConstIntCVar3("r_UseParticlesHalfResMinCoverage", CV_r_useparticles_halfres_min_coverage, 1,VF_NULL,
		"Threshold of estimated particle coverage needed before half-res rendering enabled.\n"
		"Half resolution rendering has a constant performance hit, so there's usually no gain if used for a very small number of particles\n"
		"Usage: r_UseParticlesHalfResMinCoverage [n]\n"
		"n = approx screenfulls of coverage");

	DefineConstIntCVar3("r_UseParticlesHalfResDebug", CV_r_useparticles_halfres_debug, 0,VF_NULL,
		"Render half resolution particles tinted with a color.\n"
		"Usage: r_UseParticlesHalfResDebug [0/1]");

	REGISTER_CVAR3("r_UseParticles_GIAmount", CV_r_useparticles_giamount, 0.15f, VF_NULL,
		"Global illumination amount for particles without material.\n"
		"Usage: r_UseParticles_GIAmount [n]");

  REGISTER_CVAR3("r_PostAA", CV_r_PostAA, 1, VF_NULL,
    "Enables amortized super sampling.\n"
    "Usage: r_PostAA [0/1]"
		"1: 2x SSAA, 0: disabled");

	REGISTER_CVAR3("r_PostAAMode", CV_r_PostAAMode, 2, VF_NULL,
		"Enables supported AA modes.\n"
		"Usage: r_PostAAMode [1: to enable 2x distributed SSAA, 2: video capture mode (TBD)");	

	REGISTER_CVAR3("r_PostAAEdgeFilter", CV_r_PostAAEdgeFilter, 1, VF_NULL,
		"Enables morphological edge antialiasing algorithm.\n"
		"Usage: r_PostAAEdgeFilter [0/1]. 0: disabled, 1: SMAA t2x, 2: SMAA 2x");	

	REGISTER_CVAR3("r_PostAAStencilCulling", CV_r_PostAAStencilCulling, 0, VF_NULL,
		"Enables post processed AA stencil culling.\n");
	

#if !defined(PS3) && !defined(XENON) && !defined(CAFE)
	DefineConstIntCVar3("r_PostAAInEditingMode", CV_r_PostAAInEditingMode, 1, VF_NULL,
		"Enables amortized super sampling in editing mode. Uses camera jittering which can cause flickering of helper objects\n"
		"Usage: r_PostAAInEditingMode [0/1]");	
#endif

	REGISTER_CVAR3("r_MotionBlur", CV_r_MotionBlur, 1,VF_NULL,
    "Enables per object and camera motion blur.\n"
    "Usage: r_MotionBlur [0/1/2/3]\n"
    "Default is 1 (camera motion blur on).\n"
		"1: camera motion blur\n"
		"2: camera and object motion blur\n"
		"3: debug mode\n");  

	REGISTER_CVAR3("r_UseMergedPosts", CV_r_UseMergedPosts, 1,VF_NULL,
		"Enables motion blur merged with dof.\n"
		"Usage: r_UseMergedPosts [0/1/2]\n"
		"Default is 1.\n"
		"1: fastest mode - half res rendering\n"
		"2: full res rendering mode (tbd)\n"
		"3: quality mode, hdr + fullres (tbd)\n");  
	
  REGISTER_CVAR3("r_MotionBlurShutterSpeed", CV_r_MotionBlurShutterSpeed, 0.0055f,0,
    "Sets motion blur camera shutter speed.\n"
    "Usage: r_MotionBlurShutterSpeed [0...1]\n"
    "Default is 0.0055");  

	REGISTER_CVAR3("r_MotionBlurMaxViewDist", CV_r_MotionBlurMaxViewDist, 16.0f, 0,
		"Sets motion blur max view distance for objects.\n"
		"Usage: r_MotionBlurMaxViewDist [0...1]\n"
		"Default is 16 meters");  
	
  DefineConstIntCVar3("r_MotionBlurFrameTimeScale", CV_r_MotionBlurFrameTimeScale, 0,VF_NULL,
    "Enables motion blur.frame time scaling - visually nicer on lower frame rates\n"
    "Usage: r_MotionBlurFrameTimeScale [0/1]");

  DefineConstIntCVar3("r_MotionBlurAdaptiveSampling", CV_r_MotionBlurAdaptiveSampling, 1,VF_NULL,
    "Enables motion blur.adaptive sampling setting depending on movement amount\n"
    "Usage: r_MotionBlurAdaptiveSampling [0/1]");

  DefineConstIntCVar3("r_CustomVisions", CV_r_customvisions, CUSTOMVISIONS_DEFAULT_VAL,VF_NULL,
    "Enables custom visions, like heatvision, binocular view, etc.\n"
    "Usage: r_CustomVisions [0/1/2]\n"
    "Default is 0 (disabled). 1 enables. 2 - cheaper version, no post processing");  

	DefineConstIntCVar3("r_DebugLayerEffect", CV_r_DebugLayerEffect, 0,VF_NULL,
		"Enables debug mode (independent from game code) for layer effects\n"
		"Usage: r_DebugLayerEffect [0/1/2/3/etc]\n"
		"Default is 0 (disabled). 1: 1st layer mode, etc");  

	DefineConstIntCVar3("r_Snow", CV_r_snow, 2, VF_NULL,
		"Enables snow rendering\n"
		"Usage: r_Snow [0/1/2]\n"
		"0 - disabled\n"
		"1 - enabled\n"
		"2 - enabled with snow occlusion");

	DefineConstIntCVar3("r_SnowHalfRes", CV_r_snow_halfres, 0, VF_NULL,
		"When enabled, snow renders at half resolution to conserve fill rate.\n"
		"Usage: r_SnowHalfRes [0/1]\n"
		"0 - disabled\n"
		"1 - enabled\n");

	DefineConstIntCVar3("r_SnowDisplacement", CV_r_snow_displacement, 0, VF_NULL,
		"Enables displacement for snow accumulation\n"
		"Usage: r_SnowDisplacement [0/1]\n"
		"0 - disabled\n"
		"1 - enabled");
	
	DefineConstIntCVar3("r_SnowFlakeClusters", CV_r_snowFlakeClusters, 100, VF_NULL,
		"Number of snow flake clusters.\n"
		"Usage: r_SnowFlakeClusters [n]");

  DefineConstIntCVar3("r_Rain", CV_r_rain, 2, VF_NULL,
    "Enables rain rendering\n"
    "Usage: r_Rain [0/1/2]\n"
    "0 - disabled"
		"1 - enabled"
		"2 - enabled with rain occlusion");

  REGISTER_CVAR3("r_RainAmount", CV_r_rainamount, 1.0f,VF_NULL,
    "Sets rain amount\n"
    "Usage: r_RainAmount");

  REGISTER_CVAR3("r_RainMaxViewDist", CV_r_rain_maxviewdist, 32.0f,VF_NULL,
    "Sets rain max view distance\n"
    "Usage: r_RainMaxViewDist");

	REGISTER_CVAR3("r_RainMaxViewDist_Deferred", CV_r_rain_maxviewdist_deferred, 40.f, VF_NULL,
		"Sets maximum view distance (in meters) for deferred rain reflection layer\n"
		"Usage: r_RainMaxViewDist_Deferred [n]");

	REGISTER_CVAR3("r_RainLayersPerFrame", CV_r_rainLayersPerFrame, 2, VF_NULL, "Number of rain layers to render per frame");

	REGISTER_CVAR3("r_RainDistMultiplier", CV_r_rainDistMultiplier, 2.f, VF_NULL, "Rain layer distance from camera multiplier");

	REGISTER_CVAR3("r_RainOccluderSizeTreshold", CV_r_rainOccluderSizeTreshold, 25.f, VF_NULL, "Only objects bigger than this size will occlude rain");

	REGISTER_CVAR3("r_SSReflections", CV_r_SSReflections, 0, VF_NULL,
		"Screen space reflections [0/1/2]\n"
		"1 - Noisy sharp reflections without blurring\n"
		"2 - Glossy/blurred reflections\n"
		"3 - Blurred reflections (a different blurring algorithm)\n"
		"4 - Specular+diffuse reflections (more expensive)");
	REGISTER_CVAR3("r_SSReflCutoff", CV_r_SSReflCutoff, 0.1f, VF_NULL, "Glossiness value below which reflections are disabled");
	REGISTER_CVAR3("r_SSReflExp", CV_r_SSReflExp, 0.25f, VF_NULL, "Reflection exponent, applied to glossiness material property");
	REGISTER_CVAR3("r_ssdo", CV_r_ssdo, 0, VF_NULL,
		"Screen Space Directional Occlusion [0/1/2]\n"
		"1 - Enabled for local lights and sun\n"
		"2 - Enabled for all lights and used for ambient as well (make sure to disable SSAO)"
		"99 - Enabled for lights, no smoothing applied (for debugging)");
	REGISTER_CVAR3("r_ssdoRadius", CV_r_ssdoRadius, 0.4f, VF_NULL, "SSDO radius");
	REGISTER_CVAR3("r_ssdoRadiusMin", CV_r_ssdoRadiusMin, 0.06f, VF_NULL, "Min clamped SSDO radius");
	REGISTER_CVAR3("r_ssdoRadiusMax", CV_r_ssdoRadiusMax, 0.2f, VF_NULL, "Max clamped SSDO radius");
	REGISTER_CVAR3("r_ssdoAmount", CV_r_ssdoAmount, 1.2f, VF_NULL, "Strength of the directional occlusion");
	REGISTER_CVAR3("r_ssdoAmbientAmount", CV_r_ssdoAmbientAmount, 1.0f, VF_NULL, "Strength of SSDO ambient occlusion");

	DefineConstIntCVar3("r_RainIgnoreNearest", CV_r_rain_ignore_nearest, 1, VF_NULL,
		"Disables rain wet/reflection layer for nearest objects\n"
		"Usage: r_RainIgnoreNearest [0/1]\n");

	DefineConstIntCVar3("r_DepthOfField", CV_r_dof, DOF_DEFAULT_VAL,VF_NULL,
    "Enables depth of field.\n"
    "Usage: r_DepthOfField [0/1/2]\n"
    "Default is 0 (disabled). 1 enables, 2 hdr time of day dof enabled");  

  DefineConstIntCVar3("r_DepthOfFieldBokeh", CV_r_DofBokeh, 0,VF_NULL,
    "Sets depth of field bokeh type (only for dof mode 3).\n"
    "Usage: r_DepthOfFieldBokeh [0/1/etc]\n"
    "Default is 0 (isotropic/spherical).");  

	REGISTER_CVAR3("r_DepthOfFieldBokehQuality", CV_r_DofBokehQuality, 0,VF_NULL,
		"Sets depth of field bokeh quality (samples multiplier).\n"
		"Usage: r_DepthOfFieldBokeh [0/1/etc]\n"
		"Default is 0: ingame quality, 1: high quality mode");  

	DefineConstIntCVar3("r_DepthOfFieldStencilPrepass", CV_r_dof_stencil_prepass, 0,VF_NULL,
		"Enables depth of field stencil prepass.\n"
		"Usage: r_DepthOfFieldStencilPrepass [0/1]\n"
		"Default is 0 (disabled). 1 enables");  

	DefineConstIntCVar3("r_DebugLightVolumes", CV_r_DebugLightVolumes, 0, VF_NULL,
		"0=Disable\n"
		"1=Enable\n"
		"Usage: r_DebugLightVolumes[0/1]");

  DefineConstIntCVar3("r_UseShadowsPool", CV_r_UseShadowsPool, SHADOWS_POOL_DEFAULT_VAL, VF_NULL,
    "0=Disable\n"
    "1=Enable\n"
    "Usage: r_UseShadowsPool[0/1]");
  
  REGISTER_CVAR3("r_ShadowsBias", CV_r_ShadowsBias, 0.00008f, VF_DUMPTODISK, //-0.00002
    "Select shadow map blurriness if r_ShadowsBias is activated.\n"
    "Usage: r_ShadowsBias [0.1 - 16]");

	REGISTER_CVAR3("r_ShadowsAdaptionRangeClamp", CV_r_ShadowsAdaptionRangeClamp, 0.02f, VF_DUMPTODISK, //-0.00002
		"maximum range between caster and reciever to take into account.\n"
		"Usage: r_ShadowsAdaptionRangeClamp [0.0 - 1.0], default 0.01");

	REGISTER_CVAR3("r_ShadowsAdaptionSize", CV_r_ShadowsAdaptionSize, 0.3f, VF_DUMPTODISK, //-0.00002
		"Select shadow map blurriness if r_ShadowsBias is activated.\n"
		"Usage: r_ShadowsAdaptoinSize [0 for none - 10 for rapidly changing]");

	REGISTER_CVAR3("r_ShadowsAdaptionMin", CV_r_ShadowsAdaptionMin, 0.35f, VF_DUMPTODISK, //-0.00002
		"starting kernel size, to avoid blocky shadows.\n"
		"Usage: r_ShadowsAdaptionMin [0.0 for blocky - 1.0 for blury], 0.35 is default");

	REGISTER_CVAR3("r_ShadowsParticleKernelSize", CV_r_ShadowsParticleKernelSize, 1.f, VF_DUMPTODISK,
		"Blur kernel size for particles shadows.\n"
		"Usage: r_ShadowsParticleKernelSize [0.0 hard edge - x for blur], 1. is default");
	
	REGISTER_CVAR3("r_ShadowsParticleJitterAmount", CV_r_ShadowsParticleJitterAmount, 0.5f, VF_DUMPTODISK,
		"Amount of jittering for particles shadows.\n"
		"Usage: r_ShadowsParticleJitterAmount [x], 0.5 is default");

	REGISTER_CVAR3("r_ShadowsParticleAnimJitterAmount", CV_r_ShadowsParticleAnimJitterAmount, 1.f, VF_DUMPTODISK,
		"Amount of animated jittering for particles shadows.\n"
		"Usage: r_ShadowsParticleJitterAmount [x], 1. is default");

	REGISTER_CVAR3("r_ShadowsParticleNormalEffect", CV_r_ShadowsParticleNormalEffect, 1.f, VF_DUMPTODISK,
		"Shadow taps on particles affected by normal and intensity (breaks lines and uniformity of shadows).\n"
		"Usage: r_ShadowsParticleNormalEffect [x], 1. is default");

  DefineConstIntCVar3("r_ShadowGenMode", CV_r_ShadowGenMode, 1, VF_NULL,
                   "0=Use Frustums Mask\n"
                   "1=Regenerate all sides\n"
                   "Usage: r_ShadowGenMode [0/1]");

	DefineConstIntCVar3("capture_misc_render_buffers", CV_capture_misc_render_buffers, 0, VF_NULL,
		"Captures internal render targets.\n"
		"Usage: capture_misc_render_buffers [0/1/2]\n"
		"0=Disable (default)\n"
		"1=Capture HDR, depth, shadow mask and AO buffers along with final framebuffer\n"
		"2=Capture stereo left and right buffers\n"
		"Note: Enable capturing via \"capture_frames 1\".");

  DefineConstIntCVar3("r_ShadowsUseClipVolume", CV_r_ShadowsUseClipVolume, SHADOWS_CLIP_VOL_DEFAULT_VAL, VF_DUMPTODISK,
    ".\n"
    "Usage: r_ShadowsUseClipVolume [0=Disable/1=Enable");

  REGISTER_CVAR3("r_ShadowBlur", CV_r_shadowblur, SHADOWS_BLUR_DEFAULT_VAL, VF_DUMPTODISK,
    "Selected shadow map screenspace blurring technique.\n"
    "Usage: r_ShadowBlur [0=no blurring(fastest)/1=blur/2=blur/3=blur without leaking(slower)]");
  DefineConstIntCVar3("r_ShadowTexFormat", CV_r_shadowtexformat, 4, VF_NULL,
    "0=use R16G16 texture format for depth map, 1=try to use R16 format if supported as render target\n"
    "2=use R32F texture format for depth map\n"
    "3=use ATI's DF24 texture format for depth map\n"
    "4=use NVIDIA's D24S8 texture format for depth map\n"
    "5=use NVIDIA's D16 texture format for depth map\n"
    "Usage: r_ShadowTexFormat [0-5]");
  
  DefineConstIntCVar3("r_ShadowsDeferredMode", CV_r_ShadowsDeferredMode, 1, VF_NULL,
    "0=Quad light bounds\n"
    "1=Use light volumes\n"
    "Usage: r_ShadowsDeferredMode [0/1]");
  DefineConstIntCVar3("r_ShadowsMaskResolution", CV_r_ShadowsMaskResolution, 0, VF_NULL,
    "0=per pixel shadow mask\n"
    "1=horizontal half resolution shadow mask\n"
    "2=horizontal and vertical half resolution shadow mask\n"
    "Usage: r_ShadowsMaskResolution [0/1/2]");
  DefineConstIntCVar3("r_ShadowsMaskDownScale", CV_r_ShadowsMaskDownScale, 0, VF_NULL,
    "Saves video memory by using lower resolution for shadow masks except first one\n"
    "0=per pixel shadow mask\n"
    "1=half resolution shadow mask\n"
    "Usage: r_ShadowsMaskDownScale [0/1]");











	DefineConstIntCVar3("r_ShadowsStencilPrePass", CV_r_ShadowsStencilPrePass, 1, VF_NULL,
		"1=Use Stencil pre-pass for shadows\n"
		"Usage: r_ShadowsStencilPrePass [0/1]");

  REGISTER_CVAR3("r_ShadowsDepthBoundNV", CV_r_ShadowsDepthBoundNV, 0, VF_NULL,
    "1=use NV Depth Bound extension\n"
    "Usage: r_ShadowsDepthBoundNV [0/1]");
	REGISTER_CVAR3("r_ShadowsPCFiltering", CV_r_ShadowsPCFiltering, 1, VF_NULL,
		"1=use PCF for shadows\n"
		"Usage: r_ShadowsPCFiltering [0/1]");
  DefineConstIntCVar3("r_ShadowsForwardPass", CV_r_ShadowsForwardPass, 1, VF_NULL,
    "1=use Forward prepare depth maps pass\n"
    "Usage: CV_r_ShadowsForwardPass [0/1]");
  REGISTER_CVAR3("r_ShadowBluriness", CV_r_shadowbluriness, 1.0f, VF_DUMPTODISK,
    "Select shadow map blurriness if r_ShadowBlur is activated.\n"
    "Usage: r_ShadowBluriness [0.1 - 16]");
	REGISTER_CVAR3("r_ShadowJittering", CV_r_shadow_jittering, 3.4f, VF_NULL,
		"Activate shadow map jittering.\n"
		"Usage: r_ShadowJittering [0=off, 1=on]");
	REGISTER_CVAR3("r_VarianceShadowMapBlurAmount", CV_r_VarianceShadowMapBlurAmount, 1.0f, VF_DUMPTODISK,
		"Activate shadow map blur.\n"
		"Usage: r_VarianceShadowMapBlurAmount [0=deactivate, >0 to specify blur amount (1=normal)]\n");
  DefineConstIntCVar3("r_DebugLights", CV_r_debuglights, 0,VF_CHEAT,
		"Display dynamic lights for debugging.\n"
		"Usage: r_DebugLights [0/1/2/3]\n"
		"Default is 0 (off). Set to 1 to display centers of light sources,\n"
		"or set to 2 to display light centers and attenuation spheres, 3 to get light properties to the screen");
  DefineConstIntCVar3( "r_ShadowsGridAligned", CV_r_ShadowsGridAligned, 1, VF_DUMPTODISK,
      "Selects algorithm to use for shadow mask generation:\n"
      "0 - Disable shadows snapping\n"
      "1 - Enable shadows snapping" );
  DefineConstIntCVar3( "r_ShadowGenGS", CV_r_ShadowGenGS, 0, VF_DUMPTODISK,
    "Use geometry shader for shadow map generation (DX11 only, don't change at runtime)\n"
		"Usage: r_ShadowGenGS [0=off, 1=on]\n");
  DefineConstIntCVar3( "r_ShadowPass", CV_r_ShadowPass, 1, VF_NULL,
    "Process shadow pass" );
  DefineConstIntCVar3( "r_ShadowGen", CV_r_ShadowGen, 1, VF_NULL,
    "0=disable shadow map updates, 1=enable shadow map updates" );
	DefineConstIntCVar3( "r_ShadowPoolMaxFrames", CV_r_ShadowPoolMaxFrames, 30, VF_NULL,
		"Maximum number of frames a shadow can exist in the pool" );
	REGISTER_CVAR3("r_ShadowPoolMaxTimeslicedUpdatesPerFrame", CV_r_ShadowPoolMaxTimeslicedUpdatesPerFrame, 1, VF_NULL,
		"Max number of time sliced shadow pool updates allowed per frame");

	REGISTER_CVAR3( "r_RenderMeshHashGridUnitSize", CV_r_RenderMeshHashGridUnitSize, .5f, VF_NULL, "Controls density of render mesh triangle indexing structures" );

	REGISTER_CVAR3( "r_SSAO", CV_r_SSAO, 5, VF_NULL, 
		"Screen space ambient occlusion:\n"
		"0 - disabled\n"
		"1 - SSAO technique with normals\n"
		"2 - SSAO technique with normals and temporal accumulation\n"
		"3 - Volumetric Obscurance technique with jittering\n"
		"4 - Volumetric Obscurance technique with jittering and temporal accumulation\n"
		"5 - VO variation with multiple radii"
	);

	REGISTER_CVAR3( "r_SSAOAmount", CV_r_SSAO_amount,				1.00f, VF_NULL, "Controls how much SSAO affects ambient" );
	REGISTER_CVAR3( "r_SSAODownscale", CV_r_SSAO_downscale,	0, VF_NULL, "Use downscaled computations for SSAO" );
	REGISTER_CVAR3( "r_SSAORadius",	CV_r_SSAO_radius,				1.50f, VF_NULL, "Controls size of area tested" );
	REGISTER_CVAR3( "r_SSAOQuality", CV_r_SSAO_quality,			3, VF_NULL, "SSAO shader quality[0 - Low spec, 1 - Medium spec, 2 - High spec, 3-3 Highest spec]" );
	REGISTER_CVAR3( "r_SSAOContrast", CV_r_SSAO_contrast,		1.00f, VF_NULL, "SSAO contrast coefficient (higher contrast highlights edges)" );
	REGISTER_CVAR3( "r_SSAOTemporalConvergence", CV_r_SSAO_temporalConvergence,0.7f, VF_NULL, "Temporal SSAO update/convergence speed" );
	REGISTER_CVAR3( "r_SSAOSmallRadiusRatio",	CV_r_SSAO_smallradiusratio, 0.30f, VF_NULL, "Scale factor for small radius in multi-radii SSAO" );
	REGISTER_CVAR3( "r_SSAOLargeRadiusRatio",	CV_r_SSAO_largeradiusratio, 4.00f, VF_NULL, "Scale factor for large radius in multi-radii SSAO" );
	REGISTER_CVAR3( "r_SSAOBrighteningMargin",	CV_r_SSAO_brighteningmargin, 1.1f, VF_NULL, 
		"Margin for brightening in multi-radii SSAO:\n" 
		"1.0 - no brightening allowed\n"
		"1.1 - SSAO can make some part of the scene brighter up to 10%, default"
	);

  DefineConstIntCVar3( "r_TerrainAO", CV_r_TerrainAO, 7, 0, "7=Activate terrain AO deferred passes" );
  DefineConstIntCVar3( "r_TerrainAO_FadeDist", CV_r_TerrainAO_FadeDist, 8, 0, "Controls sky light fading in tree canopy in Z direction" );

  DefineConstIntCVar3("r_LightsSinglePass", CV_r_lightssinglepass, 1, VF_NULL,"");
  
  DefineConstIntCVar3("r_ShowDynTextures",CV_r_showdyntextures,0, VF_NULL,
	  "Display a dyn. textures, filtered by r_ShowDynTexturesFilter\n"
	  "Usage: r_ShowDynTextures 0/1/2\n"
	  "Default is 0. Set to 1 to show all dynamic textures or 2 to display only the ones used in this frame\n"
    "Textures are sorted by memory usage");

  REGISTER_CVAR3("r_ShowDynTexturesMaxCount",CV_r_ShowDynTexturesMaxCount,36, VF_NULL,
    "Allows to adjust number of textures shown on the screen\n"
    "Usage: r_ShowDynTexturesMaxCount [1...36]\n"
    "Default is 36");

  CV_r_ShowDynTexturesFilter = REGISTER_STRING("r_ShowDynTexturesFilter","*", VF_NULL,
    "Usage: r_ShowDynTexturesFilter *end\n"
		"Usage: r_ShowDynTexturesFilter *mid*\n"
		"Usage: r_ShowDynTexturesFilter start*\n"
    "Default is *. Set to 'pattern' to show only specific textures (activate r_ShowDynTextures)");

	CV_r_ShaderCompilerServer = REGISTER_STRING("r_ShaderCompilerServer","8core5", VF_NULL,
		"Usage: r_ShaderCompilerServer localhost \n"
		"Default is 8core5 ");

  {
    const SFileVersion & ver = gEnv->pSystem->GetFileVersion();

    char versionString[128];
    memset(versionString, 0, sizeof(versionString));
    sprintf(versionString, "Build Version: %d.%d.%d.%d", ver.v[3], ver.v[2], ver.v[1], ver.v[0]);

    CV_r_ShaderEmailTags = REGISTER_STRING("r_ShaderEmailTags",versionString, VF_NULL,
      "Adds optional tags to shader error emails e.g. own name or build run\n"
      "Usage: r_ShaderEmailTags \"some set of tags or text\" \n"
      "Default is build version ");
  }

	REGISTER_CVAR3("r_ShaderCompilerPort", CV_r_ShaderCompilerPort, 61453, VF_NULL,
		"set user defined port of the shader compile server.\n"
		"Usage: r_ShaderCompilerPort 61453 #\n"
		"Default is 61453");

	REGISTER_CVAR3("r_ShaderCompilerDontCache", CV_r_ShaderCompilerDontCache, 0, VF_NULL,
		"Disables caching on server side.\n"
		"Usage: r_ShaderCompilerDontCache 0 #\n"
		"Default is 0");

	REGISTER_CVAR3("r_RC_AutoInvoke", CV_r_rc_autoinvoke, (gEnv->pSystem->IsDevMode() ? 1:0) , VF_NULL,
		"Enable calling the resource compiler (rc.exe) to compile TIF file to DDS files if the date check\n"
		"shows that the destination is older or does not exist.\n"
		"Usage: r_RC_AutoInvoke 0 (default is 1)");

  DefineConstIntCVar3("r_Glow", CV_r_glow,1, VF_NULL,
    "Toggles the glow effect.\n"
    "Usage: r_Glow [0/1]\n"
    "Default is 0 (off). Set to 1 to enable glow effect.");

  REGISTER_CVAR3("r_GlowAnamorphicFlares", CV_r_glowanamorphicflares, 0, VF_NULL,
    "Toggles the anamorphic flares effect.\n"
    "Usage: r_GlowAnamorphicFlares [0/1]\n"
    "Default is 0 (off). Set to 1 to enable.");

  DefineConstIntCVar3("r_NightVision", CV_r_NightVision, 2, VF_NULL,
    "Toggles nightvision enabling.\n"
    "Usage: r_NightVision [0/1/2/3/4]\n"
    "Default is 2 (HDR). "		
		"Set to 1 (older version - kept for backward compatibility)"
		"Set to 3 to enable debug mode (force enabling)."
		"Set to 4 to enable debug mode (older version - force enabling)."
		"Set to 0 to completely disable nightvision. ");

	REGISTER_CVAR3("r_NightVisionFinalMul", CV_r_NightVisionFinalMul, 3.0f, VF_NULL,
		"Set nightvision final color multiplier for fine tunning.\n");
	REGISTER_CVAR3("r_NightVisionAmbientMul", CV_r_NightVisionAmbientMul, 6.0f, VF_NULL,
		"Set nightvision ambient color multiplier.\n");
	REGISTER_CVAR3("r_NightVisionBrightLevel", CV_r_NightVisionBrightLevel, 3.0f, VF_NULL,
		"Set nightvision bloom brightlevel.\n");
	REGISTER_CVAR3("r_NightVisionViewDist", CV_r_NightVisionViewDist, 100.0f, VF_NULL,
		"Set nightvision ambient view distance.\n");	
	REGISTER_CVAR3("r_NightVisionSonarLifetime", CV_r_NightVisionSonarLifetime, 2.0f, VF_NULL,
		"Set nightvision sonar hints lifetime.\n");
	REGISTER_CVAR3("r_NightVisionSonarMultiplier", CV_r_NightVisionSonarMultiplier, 0.2f, VF_NULL,
		"Set nightvision sonar hints color multiplier.\n");
	REGISTER_CVAR3("r_NightVisionSonarRadius", CV_r_NightVisionSonarRadius, 32.0f, VF_NULL,
		"Set nightvision sonar hints radius.\n");
	REGISTER_CVAR3("r_NightVisionCamMovNoiseAmount", CV_r_NightVisionCamMovNoiseAmount, 0.5f, VF_NULL,
		"Set nightvision noise amount based on camera movement.\n");
	REGISTER_CVAR3("r_NightVisionCamMovNoiseBlendSpeed", CV_r_NightVisionCamMovNoiseBlendSpeed, 2.0f, VF_NULL,
		"Set nightvision noise amount blend speed.\n");

	REGISTER_CVAR3("r_dofMinZ", CV_r_dofMinZ, 0.0f, VF_NULL,
		"Set dof min z distance, anything behind this distance will get out focus. (good default value 0.4) \n");

	REGISTER_CVAR3("r_dofMinZScale", CV_r_dofMinZScale, 0.0f, VF_NULL,
		"Set dof min z out of focus strenght (good default value - 1.0f)\n");

	REGISTER_CVAR3("r_dofMinZBlendMult", CV_r_dofMinZBlendMult, 1.0f, VF_NULL,
		"Set dof min z blend multiplier (bigger value means faster blendind transition)\n");

	DefineConstIntCVar3("r_SonarVision", CV_r_SonarVision, 1, VF_NULL,
		"Toggles sonar vision enabling.\n"
		"Usage: r_SonarVision [0/1]\n"
		"Default is 1 (on). Set to 2 to enable debug mode (force enabling). Set to 0 to completely disable sonar vision modes.");

	DefineConstIntCVar3("r_ThermalVision", CV_r_ThermalVision, 1, VF_NULL,
		"Toggles termal vision enabling.\n"
		"Usage: r_ThermalVision [0/1]\n"
		"Default is 1 (on). Set to 2 to enable debug mode (force enabling). Set to 0 to completely disable termal vision modes.");

	REGISTER_CVAR3("r_ThermalVisionViewDistance", CV_r_ThermalVisionViewDistance, 150.0f, VF_NULL,
		"Toggles thermal vision distance attenuation.\n"
		"Default is 150 (meters)");

	DefineConstIntCVar3("r_ThermalVisionViewCloakFrequencyPrimary", CV_r_ThermalVisionViewCloakFrequencyPrimary, 1, VF_NULL,
		"Sets thermal vision cloaked-object flicker primary frequency.\n"
		"Usage: r_ThermalVisionViewCloakFrequencyPrimary [1+]\n"
		"When looking at a refracting (cloaked) object sets the inverse frequency of the primary sine wave for the objects heat. Higher = slower");

	DefineConstIntCVar3("r_ThermalVisionViewCloakFrequencySecondary", CV_r_ThermalVisionViewCloakFrequencySecondary, 1, VF_NULL,
		"Sets thermal vision cloaked-object flicker secondary frequency.\n"
		"Usage: r_ThermalVisionViewCloakFrequencySecondary [1+]\n"
		"When looking at a refracting (cloaked) object sets the inverse frequency of the secondary sine wave for the objects heat. Higher = slower");

	REGISTER_CVAR3("r_ThermalVisionViewCloakFlickerMinIntensity", CV_r_ThermalVisionViewCloakFlickerMinIntensity, 1.0f, VF_NULL,
		"Sets thermal vision cloaked-object flicker random min intensity.\n"
		"Usage: r_ThermalVisionViewCloakFlickerMinIntensity [0.0+]\n"
		"When looking at a refracting (cloaked) object sets the min scaling factor at which the object displays hot in thermal vision");

	REGISTER_CVAR3("r_ThermalVisionViewCloakFlickerMaxIntensity", CV_r_ThermalVisionViewCloakFlickerMaxIntensity, 1.0f, VF_NULL,
		"Sets thermal vision cloaked-object flicker random max intensity.\n"
		"Usage: r_ThermalVisionViewCloakFlickerMaxIntensity [0.0+]\n"
		"When looking at a refracting (cloaked) object sets the min scaling factor at which the object displays hot in thermal vision");

  REGISTER_CVAR3("r_refraction", CV_r_refraction, 1, VF_NULL,
		"Enables refraction.\n"
		"Usage: r_refraction [0/1]\n"
		"Default is 1 (on). Set to 0 to disable.");  

  REGISTER_CVAR3("r_sunshafts", CV_r_sunshafts, SUNSHAFTS_DEFAULT_VAL, VF_NULL,
    "Enables sun shafts.\n"
    "Usage: r_sunshafts [0/1]\n"
    "Default is 1 (on). Set to 0 to disable.");  

  DefineConstIntCVar3("r_pointslightshafts", CV_r_pointlightshafts, 0, VF_NULL,
    "Enables point light shafts.\n"
    "Usage: r_pointslightshafts [0/1]\n"
    "Default is 1 (on). Set to 0 to disable.");  

	
	DefineConstIntCVar3("r_PostProcessEffects", CV_r_PostProcess, 1, VF_CHEAT,
		"Enables post processing special effects.\n"
		"Usage: r_PostProcessEffects [0/1/2]\n"
		"Default is 1 (enabled). 2 enables and displays active effects"); 

  DefineConstIntCVar3("r_PostProcessParamsBlending", CV_r_PostProcessParamsBlending, 1, VF_NULL,
    "Enables post processing effects parameters smooth blending\n"
    "Usage: r_PostProcessEffectsParamsBlending [0/1]\n"
    "Default is 1 (enabled)."); 

	REGISTER_CVAR3("r_PostprocessParamsBlendingTimeScale", CV_r_PostprocessParamsBlendingTimeScale, 12.0f, VF_NULL,
		"Sets post processing effects parameters smooth blending time scale\n"
		"Usage: r_PostprocessParamsBlendingTimeScale [scale]\n"
		"Default is 12.0f."); 

  DefineConstIntCVar3("r_PostProcessFilters", CV_r_PostProcessFilters, 1, VF_CHEAT,
    "Enables post processing special effects filters.\n"
    "Usage: r_PostProcessEffectsFilters [0/1]\n"
    "Default is 1 (enabled). 0 disabled"); 

  DefineConstIntCVar3("r_PostProcessGameFx", CV_r_PostProcessGameFx, 1, VF_CHEAT,
    "Enables post processing special effects game fx.\n"
    "Usage: r_PostProcessEffectsGameFx [0/1]\n"
    "Default is 1 (enabled). 0 disabled"); 

  REGISTER_CVAR3("r_PostProcessReset", CV_r_PostProcessReset, 0, VF_CHEAT,
    "Enables post processing special effects reset.\n"
    "Usage: r_PostProcessEffectsReset [0/1]\n"
    "Default is 0 (disabled). 1 enabled"); 

	DefineConstIntCVar3("r_PostProcessHUD3D", CV_r_PostProcessHUD3D, 1, VF_NULL,
		"Toggles 3d hud post processing.\n"
		"Usage: r_PostProcessHUD3D [0/1]\n"
		"Default is 1 (post process hud enabled). 0 Disabled");

	DefineConstIntCVar3("r_PostProcessHUD3DDebugView", CV_r_PostProcessHUD3DDebugView, 0, VF_NULL,
		"Debug views for 3d hud post processing.\n"
		"Usage: CV_r_PostProcessHUD3DDebugView [0/1/2/3]\n"
		"Default is 0 (disabled). 1 Solid fill. 2 Wire frame. 3 Unwrap mesh onto flash texture");

	REGISTER_CVAR3("r_PostProcessHUD3DCache", CV_r_PostProcessHUD3DCache, 2, VF_NULL,
		"Enables 3d hud caching overframes.\n"
		"Usage: r_PostProcessHUD3DCache [0/1/2/3]\n"
		"Default is 0 (disabled). 1 Cache every 1 frame. 2 Every 2 frames. Etc");

	REGISTER_CVAR3("r_PostProcessHUD3DShadowAmount", CV_r_PostProcessHUD3DShadowAmount, 1.7f, VF_NULL,
		"Controls 3D HUD 'Shadow' Amount.\n"
		"Usage: r_PostProcessHUD3DShadowAmount [> 0.0]\n"
		"Default is 1.7f, higher = darker");

	REGISTER_CVAR3("r_PostProcessHUD3DGlowAmount", CV_r_PostProcessHUD3DGlowAmount, 1.0f, VF_NULL,
		"Controls 3D HUD 'Glow' Amount.\n"
		"Usage: r_PostProcessHUD3DGlowAmount [> 0.0]\n"
		"Default is 1.0f, higher = more glow");

	DefineConstIntCVar3("r_PostProcessHUD3DStencilClear", CV_r_PostProcessHUD3DStencilClear, 1, VF_NULL,
		"Enables stencil clears for flash masks when rendering HUD in 3D post process.\n"
		"Usage: r_PostProcessHUD3DNoStencilClear [0/1]\n" 
		"Default is 1 (enabled), 0 disabled");

	DefineConstIntCVar3("r_PostProcessNanoGlassDebugView", CV_r_PostProcessNanoGlassDebugView, 0, VF_NULL,
		"Debug views for Nano Glass post processing.\n"
		"Usage: CV_r_PostProcessNanoGlassDebugView [0/1]\n"
		"Default is 0 (disabled). 1 Wire frame.");

  DefineConstIntCVar3("r_ShowGammaReference", CV_r_showgammareference, 0, VF_NULL,
    "Enables display of gamma reference - useful for monitor/tv calibration.\n"
    "Usage: r_ShowGammaReference [0/1]"); 

  REGISTER_CVAR3("r_ColorGrading", CV_r_colorgrading, COLOR_GRADING_DEFAULT_VAL, VF_NULL,
    "Enables color grading.\n"
    "Usage: r_ColorGrading [0/1]");

  DefineConstIntCVar3("r_Fur", CV_r_fur, 0, VF_NULL,
    "Enables fur rendering.\n"
    "Usage: r_Fur [0/1]\n");

  REGISTER_CVAR3("r_ColorGradingSelectiveColor", CV_r_colorgrading_selectivecolor, 1, VF_NULL,
    "Enables color grading.\n"
    "Usage: r_ColorGradingSelectiveColor [0/1]");

  DefineConstIntCVar3("r_ColorGradingLevels", CV_r_colorgrading_levels, 1, VF_NULL,
    "Enables color grading.\n"
    "Usage: r_ColorGradingLevels [0/1]");

  DefineConstIntCVar3("r_ColorGradingFilters", CV_r_colorgrading_filters, 1, VF_NULL,
    "Enables color grading.\n"
    "Usage: r_ColorGradingFilters [0/1]");

	REGISTER_CVAR3("r_ColorGradingCharts", CV_r_colorgrading_charts, 1, VF_NULL,
		"Enables color grading via color charts.\n"
		"Usage: r_ColorGradingCharts [0/1]");

	REGISTER_CVAR3("r_ColorGradingChartsCache", CV_r_ColorgradingChartsCache, 4, VF_NULL,
		"Enables color grading charts update caching.\n"
		"Usage: r_ColorGradingCharts [0/1/2/etc]\n"
		"Default is 4 (update every 4 frames), 0 - always update, 1- update every other frame");
	
	DefineConstIntCVar3("r_CloudsUpdateAlways", CV_r_cloudsupdatealways, 0, VF_NULL,
		"Toggles updating of clouds each frame.\n"
		"Usage: r_CloudsUpdateAlways [0/1]\n"
		"Default is 0 (off)");
  DefineConstIntCVar3("r_CloudsDebug", CV_r_cloudsdebug, 0, VF_NULL,
    "Toggles debugging mode for clouds."
    "Usage: r_CloudsDebug [0/1/2]\n"
    "Usage: r_CloudsDebug = 1: render just screen imposters\n"
    "Usage: r_CloudsDebug = 2: render just non-screen imposters\n"
    "Default is 0 (off)");

	REGISTER_CVAR3("r_DynTexMaxSize", CV_r_dyntexmaxsize, 48, VF_NULL,""); // 48 Mb
  DefineConstIntCVar3("r_TexPreallocateAtlases", CV_r_texpreallocateatlases, TEXPREALLOCATLAS_DEFAULT_VAL, VF_NULL,"");
  REGISTER_CVAR3("r_TexAtlasSize", CV_r_texatlassize, 1024, VF_NULL,""); // 1024x1024

  DefineConstIntCVar3("r_TexPostponeLoading", CV_r_texpostponeloading, 1,VF_NULL,"");
#if !defined(XENON) && !defined(PS3) && !defined(CAFE)
  REGISTER_CVAR3("r_DynTexAtlasCloudsMaxSize", CV_r_dyntexatlascloudsmaxsize, 32,VF_NULL,""); // 32 Mb
  REGISTER_CVAR3("r_DynTexAtlasSpritesMaxSize", CV_r_dyntexatlasspritesmaxsize, 32,VF_NULL,""); // 32 Mb
  REGISTER_CVAR3("r_DynTexAtlasVoxTerrainMaxSize", CV_r_dyntexatlasvoxterrainsize, 250,VF_NULL,""); // this pool is never preallocated
  REGISTER_CVAR3("r_DynTexAtlasDynTexSrcSize", CV_r_dyntexatlasdyntexsrcsize, 16,VF_NULL,""); // this pool is never preallocated





#endif

  REGISTER_CVAR3("r_TexMinAnisotropy", CV_r_texminanisotropy, 0, VF_REQUIRE_LEVEL_RELOAD,
		"Specifies the minimum level allowed for anisotropic texture filtering.\n"
		"0(default) means abiding by the filtering setting in each material, except possibly being capped by r_TexMaxAnisotropy.");
  REGISTER_CVAR3("r_TexMaxAnisotropy", CV_r_texmaxanisotropy, TEXMAXANISOTROPY_DEFAULT_VAL, VF_REQUIRE_LEVEL_RELOAD,
		"Specifies the maximum level allowed for anisotropic texture filtering.");
  DefineConstIntCVar3("r_TexMaxSize", CV_r_texmaxsize, 0,VF_CHEAT,"");
  DefineConstIntCVar3("r_TexMinSize", CV_r_texminsize, 64,VF_CHEAT,"");

  DefineConstIntCVar3("r_TexBumpResolution", CV_r_texbumpresolution, 0, VF_DUMPTODISK,
		"Reduces texture resolution.\n"
		"Usage: r_TexBumpResolution [0/1/2 etc]\n"
		"When 0 (default) texture resolution is unaffected, 1 halves, 2 quarters etc.");

  DefineConstIntCVar3("r_TexResolution", CV_r_texresolution, 0, VF_DUMPTODISK,
		"Reduces texture resolution.\n"
		"Usage: r_TexResolution [0/1/2 etc]\n"
		"When 0 (default) texture resolution is unaffected, 1 halves, 2 quarters etc.");

  REGISTER_CVAR3( "r_TexSkyResolution", CV_r_texskyresolution, TEXSKYRES_DEFAULT_VAL, VF_DUMPTODISK,"" );
  DefineConstIntCVar3("r_TexNoAniso", CV_r_texnoaniso, 0, VF_DUMPTODISK,
		"Forces anisotropic filtering off.\n"
		"Only for D3D9");
  DefineConstIntCVar3("r_Texture_Anisotropic_Level", CV_r_texture_anisotropic_level, 1, VF_DUMPTODISK,
		"Specifies the default level for anisotropic texture filtering.");
  DefineConstIntCVar3("r_TexGrid", CV_r_texgrid, 0,VF_NULL,"");
  DefineConstIntCVar3("r_TexLog", CV_r_texlog, 0, VF_NULL,
    "Configures texture information logging.\n"
    "Usage:	r_TexLog #\n"
    "where # represents:\n"
    "	0: Texture logging off\n"
    "	1: Texture information logged to screen\n"
    "	2: All loaded textures logged to 'UsedTextures.txt'\n"
    "	3: Missing textures logged to 'MissingTextures.txt");
  DefineConstIntCVar3("r_TexNoLoad", CV_r_texnoload, 0, VF_NULL,
    "Disables loading of textures.\n"
    "Usage:	r_TexNoLoad [0/1]\n"
    "When 1 texture loading is disabled.");

	REGISTER_CVAR3("r_RenderTargetPoolSize", CV_r_rendertargetpoolsize, 0, VF_NULL,
		"Size of pool for render targets in MB.\n"
		"Default is 50(MB) for PS3 & XBox 360.");


	REGISTER_CVAR3("r_TexturesStreamPoolFragmentationCount", CV_r_texturesstreampoolfragmentationcount, 0, VF_NULL,
		"Add warning message about texture pool fragmentation when pool is overflown.\n");

	REGISTER_CVAR3("r_texturesstreampooldefragmentation", CV_r_texturesstreampooldefragmentation, 0, VF_NULL,
		"Enabled CPU (1), GPU(2) and disable (0) textures stream pool defragmentation.\n");

	REGISTER_CVAR3("r_texturesskiplowermips", CV_r_texturesskiplowermips, 0, VF_NULL,
		"Enabled skipping lower mips for X360.\n");

  REGISTER_CVAR3("r_TexturesStreamPoolSize", CV_r_texturesstreampoolsize, 128, VF_NULL,
		"Size of pool for textures streaming in MB.\n"
		"If r_TexturesStreaming is set to 2, this parameter is chosen automatically for PC.\n"
		"Default is 128(MB) for PC, 80(MB) for PS3 & XBox 360.");
  REGISTER_CVAR3("r_TexturesStreamPoolSysSize", CV_r_texturesstreampoolsyssize, 800, VF_NULL,
    "Size of system memory pool for managed textures in MB.\n"
    "If r_TexturesStreaming is set to 2, this parameter is chosen automatically for PC.\n"
    "Default is 800 MB for PC.");

  REGISTER_CVAR3("r_TexturesStreamingSync", CV_r_texturesstreamingsync, 0,VF_NULL,
		"Force only synchronous texture streaming.\n"
		"All textures will be streamed in the main thread. Useful for debug purposes.\n"
		"Usage: r_TexturesStreamingSync [0/1]\n"
		"Default is 0 (off).");
	DefineConstIntCVar3("r_TexturesStreamingResidencyEnabled", CV_r_texturesstreamingResidencyEnabled, 1, VF_NULL,
		"Toggle for resident textures streaming support.\n"
		"Usage: r_TexturesStreamingResidencyEnabled [toggle]"
		"Default is 0, 1 for enabled");
	REGISTER_CVAR3("r_TexturesStreamingResidencyTimeTestLimit", CV_r_texturesstreamingResidencyTimeTestLimit, 5.0f, VF_NULL,
		"Time limit to use for mip thrashing calculation in seconds.\n"
		"Usage: r_TexturesStreamingResidencyTimeTestLimit [time]"
		"Default is 5 seconds");
	REGISTER_CVAR3("r_TexturesStreamingResidencyTime", CV_r_texturesstreamingResidencyTime, 10.0f,VF_NULL,
		"Time to keep textures resident for before allowing them to be removed from memory.\n"
		"Usage: r_TexturesStreamingResidencyTime [Time]\n"
		"Default is 10 seconds");
	REGISTER_CVAR3("r_TexturesStreamingResidencyThrottle", CV_r_texturesstreamingResidencyThrottle, 0.5f,VF_NULL,
		"Ratio for textures to become resident.\n"
		"Usage: r_TexturesStreamingResidencyThrottle [ratio]"
		"Default is 0.5"
		"Max is 1.0 means textures will become resident sooner, Min 0.0 means textures will not become resident");
	REGISTER_CVAR3("r_TexturesStreamingMaxRequestedMB", CV_r_TexturesStreamingMaxRequestedMB, 2.f,VF_NULL,
		"Maximum amount of texture data requested from streaming system in MB.\n"
		"Usage: r_TexturesStreamingMaxRequestedMB [size]\n"
		"Default is 2.0(MB)");












	DefineConstIntCVar3("r_TexturesStreamingPostponeMips", CV_r_texturesstreamingPostponeMips, 0, VF_NULL,
		"Postpone loading of high res mipmaps to improve resolution ballance of texture streaming.\n"
		"Usage: r_TexturesStreamingPostponeMips [0/1]\n"
		"Default is 1 (on).");

  
  DefineConstIntCVar3("r_TexturesStreamingPostponeThresholdKB", CV_r_texturesstreamingPostponeThresholdKB, 1024, VF_NULL,
		"Threshold used to postpone high resolution mipmap loads in KB.\n"
		"Usage: r_TexturesStreamingPostponeThresholdKB [size]\n"
		"Default is 1024(KB)");
	DefineConstIntCVar3("r_texturesstreamingPostponeThresholdMip", CV_r_texturesstreamingPostponeThresholdMip, 1, VF_NULL,
		"Threshold used to postpone high resolution mipmaps.\n"
		"Usage: r_texturesstreamingPostponeThresholdMip [count]\n"
		"Default is 1");
	DefineConstIntCVar3("r_TexturesStreamingMinReadSizeKB", CV_r_texturesstreamingMinReadSizeKB, 64,VF_NULL,
		"Minimal read portion in KB.\n"
		"Usage: r_TexturesStreamingMinReadSizeKB [size]\n"
		"Default is 32(KB)");
	REGISTER_CVAR3("r_TexturesStreamingMaxRequestedJobs", CV_r_TexturesStreamingMaxRequestedJobs, 256,VF_NULL,
		"Maximum number of tasks submitted to streaming system.\n"
		"Usage: r_TexturesStreamingMaxRequestedJobs [jobs number]\n"
		"Default is 256 jobs");
	REGISTER_CVAR3("r_TexturesStreamingMipBias", CV_r_TexturesStreamingMipBias, 0, VF_NULL,
		"Controls how texture LOD depends from distance to the objects.\n"
		"Increasing this value will reduce amount of memory required for textures.\n"
		"Usage: r_TexturesStreamingMipBias [-4..0..4]\n"
		"Default is 0.");
	REGISTER_CVAR3("r_TexturesStreamingMipClampDVD", CV_r_TexturesStreamingMipClampDVD, 1, VF_NULL,
		"Clamp the texture mip level to certain value when streaming from DVD. 1 will never allow highest mips to be loaded for example.\n"
		"Usage: r_TexturesStreamingMipClampDVD [0..4]\n"
		"Default is 1.");
	REGISTER_CVAR3("r_TexturesStreamingDisableNoStreamDuringLoad", CV_r_TexturesStreamingDisableNoStreamDuringLoad, 0, VF_NULL,
		"Load time optimisation. When enabled, textures flagged as non-streaming will still be streamed during level load, but will have a "
		"high priority stream request added in RT_Precache. Once streamed in, the texture will remain resident\n");
	DefineConstIntCVar3("r_TexturesStreamingMipFading", CV_r_texturesstreamingmipfading, 1, VF_NULL,
		"Controls how the new texture MIP appears after being streamed in.\n"
		"This variable influences only a visual quality of appearing texture details.\n"
		"Usage: r_TexturesStreamingMipFading [0/1]\n"
		"Default is 1 (enabled).");
  DefineConstIntCVar3("r_TexturesStreamingNoUpload", CV_r_texturesstreamingnoupload, 0,VF_NULL,
		"Disable uploading data into texture from system memory. Useful for debug purposes.\n"
		"Usage: r_TexturesStreamingNoUpload [0/1]\n"
		"Default is 0 (off).");
	DefineConstIntCVar3("r_TexturesStreamingOnlyVideo", CV_r_texturesstreamingonlyvideo, 0,VF_NULL,
		"Don't store system memory copy of texture. Applicable only for PC and PS3.\n"
		"On Xenon it's on[1] by default and cannot be changed.\n"
		"Usage: r_TexturesStreamingOnlyVideo [0/1]\n"
		"Default is 0 (off) for PC and PS3, 1(on always) for XBox 360.");
  DefineConstIntCVar3("r_TexturesStreaming", CV_r_texturesstreaming, TEXSTREAMING_DEFAULT_VAL, VF_REQUIRE_APP_RESTART,
		"Enables direct streaming of textures from disk during game.\n"
		"Usage: r_TexturesStreaming [0/1/2]\n"
		"Default is 0 (off). All textures save in native format with mips in a\n"
		"cache file. Textures are then loaded into texture memory from the cache.");

  DefineConstIntCVar3("r_TexturesStreamingDebug", CV_r_TexturesStreamingDebug, 0, VF_CHEAT,
		"Enables textures streaming debug mode. (Log uploads and remove unnecessary mip levels)\n"
		"Usage: r_TexturesStreamingDebug [0/1/2]\n"
		"Default is 0 (off)."
		"1 - texture streaming log."
		"2 - Show textures hit-parade based on streaming priorities"
		"3 - Show textures hit-parade based on the memory consumed");
	CV_r_TexturesStreamingDebugfilter = REGISTER_STRING("r_TexturesStreamingDebugFilter", "", VF_CHEAT, "Filters displayed textures by name in texture streaming debug mode\n");
	REGISTER_CVAR3("r_TexturesStreamingDebugMinSize", CV_r_TexturesStreamingDebugMinSize, 100, VF_NULL,
		"Filters displayed textures by size in texture streaming debug mode");
	REGISTER_CVAR3("r_TexturesStreamingDebugMinMip", CV_r_TexturesStreamingDebugMinMip, 100, VF_NULL,
		"Filters displayed textures by loaded mip in texture streaming debug mode");
	DefineConstIntCVar3("r_TexturesStreamingDebugDumpIntoLog", CV_r_TexturesStreamingDebugDumpIntoLog, 0, VF_NULL,
		"Dump content of current texture streaming debug screen into log");
#if !defined(XENON) && !defined(PS3) && !defined(CAFE)
  REGISTER_CVAR3("r_TexturesWarmup", CV_r_textureswarmup, 1, VF_NULL,
    "Enables textures uploading to video memory after level loading\n"
    "Usage: r_TexturesWarmup[1/0]\n"
    "	0: Disabled\n"
    "	1: Enabled");
#endif
	REGISTER_CVAR3("r_TextureLodDistanceRatio", CV_r_TextureLodDistanceRatio, -1, VF_NULL,
    "Controls dynamic LOD system for textures used in materials.\n"
    "Usage: r_TextureLodDistanceRatio [-1, 0 and bigger]\n"
    "Default is -1 (completely off). Value 0 will set full LOD to all textures used in frame.\n"
    "Values bigger than 0 will activate texture LOD selection depending on distance to the objects.");

#ifndef STRIP_RENDER_THREAD
  DefineConstIntCVar3("r_MultiThreaded", CV_r_multithreaded, MULTITHREADED_DEFAULT_VAL, VF_NULL,
    "0=disabled, 1=enabling rendering in separate thread,\n"
    "2(default)=automatic detection\n"
    "should be activated before rendering");
#endif
  REGISTER_CVAR3("r_MultiGPU", CV_r_multigpu, 2, VF_NULL,
		"0=disabled, 1=extra overhead to allow SLI(NVidia) or Crossfire(ATI),\n"
		"2(default)=automatic detection (currently SLI only, means off for ATI)\n"
		"should be activated before rendering");
  DefineConstIntCVar3("r_ValidateDraw", CV_r_validateDraw, 0, VF_NULL,
    "0=disabled, 1=validate each DIP (meshes consistency, shaders, declarations, etc)");
  DefineConstIntCVar3("r_ProfileGPU", CV_r_profileGPU, 0, VF_CHEAT,
    "0=disabled, 1=profile each DIP performance (may cause very low frame rate)\n"
		"r_ProfileShaders or r_Stats needs to be activated to see the statistics");
#if defined(ENABLE_ACCURATE_RSX_PROFILING)
  DefineConstIntCVar3("r_ProfileRSX", CV_r_ProfileRSX, 0, VF_NULL,
    "0=disable, 1=enable accurate RSX profiling (will cause low and inconsistent frame rate)");
#endif

  REGISTER_CVAR3("r_MSAA", CV_r_msaa, 0, VF_DUMPTODISK | VF_REQUIRE_APP_RESTART,
		"Enables selective supersampled antialiasing.\n"
		"Usage: r_MSAA [0/1]\n"
		"Default: 0 (off).");
  REGISTER_CVAR3("r_MSAA_samples", CV_r_msaa_samples, 4, VF_DUMPTODISK | VF_REQUIRE_APP_RESTART,
		"Number of subsamples used when multisampled antialiasing is enabled.\n"
		"Usage: r_MSAA_samples N (where N is a number >= 0). Attention, N must be supported by given video hardware!\n"
		"Default: 4. Please note that various hardware implements special MSAA modes via certain combinations of\n"
		"r_MSAA_quality and r_MSAA_samples. See config/MSAAProfiles*.txt for samples.");
  REGISTER_CVAR3("r_MSAA_quality", CV_r_msaa_quality, 0, VF_DUMPTODISK | VF_REQUIRE_APP_RESTART,
		"Quality level used when multisampled antialiasing is enabled.\n"
		"Usage: r_MSAA_quality N (where N is a number >= 0). Attention, N must be supported by given video hardware!\n"
		"Default: 0. Please note that various hardware implements special MSAA modes via certain combinations of\n"
		"r_MSAA_quality and r_MSAA_samples. See config/MSAAProfiles*.txt for samples.");
	REGISTER_CVAR3("r_MSAA_debug", CV_r_msaa_debug, 0, VF_DUMPTODISK | VF_REQUIRE_APP_RESTART,
		"Enable debugging mode for msaa.\n"
		"Usage: r_MSAA_debug N (where N is debug mode > 0)\n"
		"Default: 0. disabled\n"
		"1 disable sample frequency pass\n"
		"2 visualize undersampled regions\n");

  REGISTER_CVAR3("r_MSAA_amd_resolvessubresource_hack", CV_r_msaa_amd_resolvessubresource, 1, VF_DUMPTODISK | VF_REQUIRE_APP_RESTART,
    "Enable temporary workaround for resolvesubresources poor performance on AMD.\n");
  
  DefineConstIntCVar3("r_ShowNormals", CV_r_shownormals, 0, VF_CHEAT,
		"Toggles visibility of normal vectors.\n"
		"Usage: r_ShowNormals [0/1]"
		"Default is 0 (off).");
  DefineConstIntCVar3("r_ShowLines", CV_r_showlines, 0, VF_CHEAT,
		"Toggles visibility of wireframe overlay.\n"
		"Usage: r_ShowLines [0/1]\n"
		"Default is 0 (off).");
  REGISTER_CVAR3("r_NormalsLength", CV_r_normalslength, 0.2f, VF_CHEAT,
		"Sets the length of displayed vectors.\n"
		"r_NormalsLength 0.2\n"
		"Default is 0.2 (meters). Used with r_ShowTangents and r_ShowNormals.");
  DefineConstIntCVar3("r_ShowTangents", CV_r_showtangents, 0, VF_CHEAT,
		"Toggles visibility of three tangent space vectors.\n"
		"Usage: r_ShowTangents [0/1]\n"
		"Default is 0 (off).");
  DefineConstIntCVar3("r_ShowTimeGraph", CV_r_showtimegraph, 0, VF_NULL,
		"Configures graphic display of frame-times.\n"
		"Usage: r_ShowTimeGraph [0/1/2]\n"
		"	1: Graph displayed as points."
		"	2: Graph displayed as lines."
		"Default is 0 (off).");
#ifndef EXCLUDE_DOCUMENTATION_PURPOSE
	DefineConstIntCVar3("r_DebugFontRendering", CV_r_DebugFontRendering, 0, VF_CHEAT, 
		"0=off, 1=display various features of the font rendering to verify function and to document usage");
#endif // EXCLUDE_DOCUMENTATION_PURPOSE
  DefineConstIntCVar3("profileStreaming", CV_profileStreaming, 0, VF_NULL,
    "Profiles streaming of different assets.\n"
    "Usage: profileStreaming [0/1/2]\n"
    "	1: Graph displayed as points."
    "	2: Graph displayed as lines."
    "Default is 0 (off).");
  DefineConstIntCVar3("r_GraphStyle", CV_r_graphstyle, 0,VF_NULL,"");
  DefineConstIntCVar3("r_ShowMT", CV_r_showmt, 0, VF_NULL,
    "Shows render multithreading graphs.\n"
    "Usage: r_ShowMT [0/1]\n"
    "Default is 0 (off).");
  DefineConstIntCVar3("r_ShowBufferUsage", CV_r_showbufferusage, 0, VF_NULL,
    "Shows usage of statically allocated buffers.\n"
    "Usage: r_ShowBufferUSage [0/1]\n"
    "Default is 0 (off).");
#ifndef CONSOLE_CONST_CVAR_MODE
  DefineConstIntCVar3("r_LogVBuffers", CV_r_logVBuffers, 0, VF_CHEAT,
		"Logs vertex buffers in memory to 'LogVBuffers.txt'.\n"
		"Usage: r_LogVBuffers [0/1]\n"
		"Default is 0 (off).")->SetOnChangeCallback(GetLogVBuffersStatic);
#endif
  DefineConstIntCVar3("r_LogTexStreaming", CV_r_logTexStreaming, 0,VF_CHEAT,
		"Logs streaming info to Direct3DLogStreaming.txt\n"
		"0: off\n"
		"1: normal\n"
		"2: extended");
  DefineConstIntCVar3("r_LogShaders", CV_r_logShaders, 0,VF_CHEAT,
    "Logs shaders info to Direct3DLogShaders.txt\n"
    "0: off\n"
    "1: normal\n"
    "2: extended");
  REGISTER_CVAR3("r_Flush", CV_r_flush, 1,VF_NULL,""); // this causes the game to freeze (infinite loop) - do not use

  DefineConstIntCVar3("r_OptimisedLightSetup", CV_r_optimisedlightsetup, 2,VF_NULL,"");

  DefineConstIntCVar3("r_ShadersDebug", CV_r_shadersdebug, 0, VF_DUMPTODISK,
		"Enable special logging when shaders become compiled\n"
		"Usage: r_ShadersDebug [0/1/2/3]\n"
		" 1 = assembly into directory Main/{Game}/shaders/cache/d3d9\n"
		" 2 = compiler input into directory Main/{Game}/testcg\n"
		" 3 = compiler input with debug information (useful for PIX etc./{Game}/testcg_1pass\n"
		"Default is 0 (off)");
  
#if !defined (XENON) && !defined(PS3) && !defined(CAFE)
	REGISTER_CVAR3("r_ShadersCafe", CV_r_shaderscafe, 0, VF_NULL, "");
  REGISTER_CVAR3("r_ShadersXenon", CV_r_shadersxenon, 0, VF_NULL, "");
  REGISTER_CVAR3("r_ShadersPS3", CV_r_shadersps3, 0, VF_NULL, "");
  REGISTER_CVAR3("r_ShadersDX9", CV_r_shadersdx9, 1, VF_NULL, "");
  REGISTER_CVAR3("r_ShadersDX11", CV_r_shadersdx11, 1, VF_NULL, "");
#endif

  DefineConstIntCVar3("r_ShadersIgnoreIncludesChanging", CV_r_shadersignoreincludeschanging, 0,VF_NULL,"");
  DefineConstIntCVar3("r_ShadersLazyUnload", CV_r_shaderslazyunload, 0, VF_NULL, "");  

	REGISTER_CVAR3("r_ShadersPreactivate", CV_r_shaderspreactivate, 1, VF_DUMPTODISK,"");
  REGISTER_CVAR3("r_ShadersIntCompiler", CV_r_shadersintcompiler, 1, VF_DUMPTODISK,"");

	REGISTER_CVAR3("r_ShadersNoCompile", CV_r_shadersnocompile, SHAQDERSNOCOMPILE_DEFAULT_VAL, VF_NULL,"");

	REGISTER_CVAR3("r_ShadersRemoteCompiler", CV_r_shadersremotecompiler, 0, VF_DUMPTODISK,"");
  REGISTER_CVAR3("r_ShadersAsyncCompiling", CV_r_shadersasynccompiling, 1, VF_NULL,
		"Enable asynchronous shader compiling\n"
		"Usage: r_ShadersAsyncCompiling [0/1/2/3]\n"
		" 0 = off, (stalling) shaders compiling\n"
		" 1 = on, shaders are compiled in parallel, missing shaders are rendered in yellow\n"
		" 2 = on, shaders are compiled in parallel, missing shaders are not rendered\n"
    " 3 = on, shaders are compiled in parallel in precache mode");
  REGISTER_CVAR3("r_ShadersAsyncActivation", CV_r_shadersasyncactivation, 1, VF_NULL,
    "Enable asynchronous shader activation\n"
    "Usage: r_ShadersAsyncActivation [0/1]\n"
    " 0 = off, (stalling) synchronous shaders activation\n"
    " 1 = on, shaders are activated/streamed asynchronously\n");

	DefineConstIntCVar3("r_ShadersEditing", CV_r_shadersediting, 0, VF_NULL,"Force all cvars to settings, which allow shader editing");

	DefineConstIntCVar3("r_ShadersCompileAutoActivate", CV_r_shaderscompileautoactivate, 0, VF_NULL,"Automatically reenable shader compilation if outdated shader is detected");

	REGISTER_CVAR3("r_CloakLightScale", CV_r_cloakLightScale, 0.25f, VF_NULL, "Cloak light scale - default = 0.25");
	REGISTER_CVAR3("r_CloakTransitionLightScale", CV_r_cloakTransitionLightScale, 1.0f, VF_NULL, "Cloak transition light scale - default = 1.0");
	REGISTER_CVAR3("r_CloakFadeByDist", CV_r_cloakFadeByDist, 0, VF_NULL, "Cloak fade by distance - default = false");
	REGISTER_CVAR3("r_CloakFadeLightScale", CV_r_cloakFadeLightScale, 0.25f, VF_NULL, "Cloak fade light scale - default = 0.25");
	REGISTER_CVAR3("r_CloakFadeMinDistSq", CV_r_cloakFadeStartDistSq, 1.0f, VF_NULL, "Cloak fade start distance squared - default = 1.0");
	REGISTER_CVAR3("r_CloakFadeMaxDistSq", CV_r_cloakFadeEndDistSq, 25.0f, VF_NULL, "Cloak fade end distance squared - default = 25.0");
	REGISTER_CVAR3("r_CloakFadeMinValue", CV_r_cloakFadeMinValue, 0.2f, VF_NULL, "Cloak fade minimum value (between 0 and 1) - default = 0.2");
	REGISTER_CVAR3("r_CloakRefractionFadeByDist", CV_r_cloakRefractionFadeByDist, 0, VF_NULL, "Cloak refraction fade by distance - default = false");
	REGISTER_CVAR3("r_CloakRefractionFadeMinDistSq", CV_r_cloakRefractionFadeStartDistSq, 1.0f, VF_NULL, "Cloak refraction fade start distance squared - default = 1.0");
	REGISTER_CVAR3("r_CloakRefractionFadeMaxDistSq", CV_r_cloakRefractionFadeEndDistSq, 25.0f, VF_NULL, "Cloak refraction fade end distance squared - default = 25.0");
	REGISTER_CVAR3("r_CloakRefractionFadeMinValue", CV_r_cloakRefractionFadeMinValue, 0.2f, VF_NULL, "Cloak refraction fade minimum value (between 0 and 1) - default = 0.2");
  REGISTER_CVAR3("r_CloakMinLightValue", CV_r_cloakMinLightValue, 0.0f, VF_NULL, "Cloak min light value - default = 0.0");
	REGISTER_CVAR3("r_CloakHeatScale", CV_r_cloakHeatScale, 1.0f, VF_NULL, "Cloak heat scale for thermal vision - default = 1.0");
	REGISTER_CVAR3("r_CloakRenderInThermalVision", CV_r_cloakRenderInThermalVision, 0, VF_NULL, "Render cloak in thermal vision - default = 0");
	REGISTER_CVAR3("r_CloakMinAmbientOutdoors", CV_r_cloakMinAmbientOutdoors, 8.0f, VF_CHEAT, "Cloak minimum ambient outdoors");
	REGISTER_CVAR3("r_CloakMinAmbientIndoors", CV_r_cloakMinAmbientIndoors, 2.0f, VF_CHEAT, "Cloak minimum ambient indoors");
	REGISTER_CVAR3("r_CloakSparksAlpha", CV_r_cloakSparksAlpha, 1.0f, VF_CHEAT, "Cloak sparks alpha");
	REGISTER_CVAR3("r_CloakInterferenceSparksAlpha", CV_r_cloakInterferenceSparksAlpha, 1000.0f, VF_CHEAT, "Cloak interference sparks alpha");
	REGISTER_CVAR3("r_cloakHighlightStrength", CV_r_cloakHighlightStrength, 100.0f, VF_CHEAT, "Cloak hightlight strength");
	REGISTER_CVAR3("r_ArmourPulseSpeedMultiplier", CV_r_armourPulseSpeedMultiplier, 1.0f, VF_NULL, "Armour pulse speed multiplier - default = 1.0");
	REGISTER_CVAR3("r_MaxSuitPulseSpeedMultiplier", CV_r_maxSuitPulseSpeedMultiplier, 1.0f, VF_NULL, "Max suit pulse speed multiplier - default = 1.0");

  REGISTER_CVAR3("r_ShadersAsyncMaxThreads", CV_r_shadersasyncmaxthreads, 1, VF_DUMPTODISK,"");
  REGISTER_CVAR3("r_ShadersCacheOptimiseLog", CV_r_shaderscacheoptimiselog, 0, VF_NULL,"");
  DefineConstIntCVar3("r_ShadersPrecacheAllLights", CV_r_shadersprecachealllights, 1,VF_NULL,"");
  REGISTER_CVAR3("r_ShadersSubmitRequestline", CV_r_shaderssubmitrequestline, 1,VF_NULL,"");
	REGISTER_CVAR3("r_ShadersUseInstanceLookUpTable", CV_r_shadersuseinstancelookuptable, 0,VF_NULL,
		"Use lookup table to search for shader instances. Speeds up the process, but uses more memory. Handy for shader generation.");

	bool bShaderLogCacheMisses = true;
#if defined(_RELEASE)
	bShaderLogCacheMisses = false;
#endif
	REGISTER_CVAR3("r_ShadersLogCacheMisses", CV_r_shaderslogcachemisses, bShaderLogCacheMisses, VF_NULL,
		"Log all shader caches misses on HD (both level and global shader cache misses).");

  DefineConstIntCVar3("r_DebugRenderMode", CV_r_debugrendermode, 0, VF_CHEAT,"");
  DefineConstIntCVar3("r_DebugRefraction", CV_r_debugrefraction, 0, VF_CHEAT,
    "Debug refraction usage. Displays red instead of refraction\n"
    "Usage: r_DebugRefraction\n"
    "Default is 0 (off)");
  REGISTER_CVAR3("r_DebugVoxTerrainX", CV_r_DebugVoxTerrainX, 0, VF_CHEAT,"");
  REGISTER_CVAR3("r_DebugVoxTerrainY", CV_r_DebugVoxTerrainY, 0, VF_CHEAT,"");
  
  DefineConstIntCVar3("r_MeshPrecache", CV_r_meshprecache, 1, VF_NULL, "");
  REGISTER_CVAR3("r_MeshPoolSize", CV_r_meshpoolsize, RENDERER_DEFAULT_MESHPOOLSIZE, VF_NULL, 
    "The size of the pool for render data in kilobytes. "
    "Disabled by default on PC (mesh data allocated on heap)."
    "Enabled by default PS3. Requires app restart to change.");
  REGISTER_CVAR3("r_MeshVolatilePoolSize", CV_r_meshvolatilepoolsize, RENDERER_DEFAULT_MESHPOOLSIZE, VF_NULL, 
    "The size of the pool for volatile render data in kilobytes. "
    "Disabled by default on PC (mesh data allocated on heap)."
    "Enabled by default PS3. Requires app restart to change.");

  CV_r_excludeshader = REGISTER_STRING("r_ExcludeShader", "0", VF_CHEAT,
		"Exclude the named shader from the render list.\n"
		"Usage: r_ExcludeShader ShaderName\n"
		"Sometimes this is useful when debugging.");

  CV_r_excludemesh = REGISTER_STRING("r_ExcludeMesh", "", VF_CHEAT,
    "Exclude or ShowOnly the named mesh from the render list.\n"
    "Usage: r_ExcludeShader Name\n"
    "Usage: r_ExcludeShader !Name\n"
    "Sometimes this is useful when debugging.");

  DefineConstIntCVar3("r_ProfileShaders", CV_r_profileshaders, 0, VF_CHEAT,
		"Enables display of render profiling information.\n"
		"Usage: r_ProfileShaders [0/1]\n"
		"Default is 0 (off). Set to 1 to display profiling\n"
		"of rendered shaders.");
  DefineConstIntCVar3("r_ProfileShadersSmooth", CV_r_ProfileShadersSmooth, 4, VF_CHEAT,
    "Smooth time information.\n"
    "Usage: r_ProfileShadersSmooth [0-10]");
  DefineConstIntCVar3("r_ProfileShadersGroupByName", CV_r_ProfileShadersGroupByName, 1, VF_CHEAT,
    "Group items by name ignoring RT flags.\n"
    "Usage: r_ProfileShaders [0/1]");
  
/*  REGISTER_CVAR3("r_EnvCMWrite", CV_r_envcmwrite, 0, VF_NULL,
		"Writes cube-map textures to disk.\n"
		"Usage: r_EnvCMWrite [0/1]\n"
		"Default is 0 (off). The textures are written to 'Cube_posx.jpg'\n"
		"'Cube_negx.jpg',...,'Cube_negz.jpg'. At least one of the real-time\n"
		"cube-map shaders should be present in the current scene.");
  */
  REGISTER_CVAR3("r_EnvCMResolution", CV_r_envcmresolution, 1, VF_DUMPTODISK,
		"Sets resolution for target environment cubemap, in pixels.\n"
		"Usage: r_EnvCMResolution #\n"
		"where # represents:\n"
		"	0: 64\n"
		"	1: 128\n"
		"	2: 256\n"
		"Default is 2 (256 by 256 pixels).");

  REGISTER_CVAR3("r_EnvTexResolution", CV_r_envtexresolution, ENVTEXRES_DEFAULT_VAL, VF_DUMPTODISK,
		"Sets resolution for 2d target environment texture, in pixels.\n"
		"Usage: r_EnvTexResolution #\n"
		"where # represents:\n"
		"	0: 64\n"
		"	1: 128\n"
		"	2: 256\n"
		"	3: 512\n"
		"Default is 3 (512 by 512 pixels).");
  
  REGISTER_CVAR3("r_WaterUpdateDistance", CV_r_waterupdateDistance, 2.0f, VF_NULL,"");
  
  REGISTER_CVAR3("r_WaterUpdateFactor", CV_r_waterupdateFactor, 0.01f, VF_DUMPTODISK,
		"Distance factor for water reflected texture updating.\n"
		"Usage: r_WaterUpdateFactor 0.01\n"
		"Default is 0.01. 0 means update every frame");
  
  REGISTER_CVAR3("r_EnvLCMupdateInterval", CV_r_envlcmupdateinterval, 0.1f, VF_DUMPTODISK,
					"LEGACY - not used");
//		"Sets the interval between environmental cube map texture updates.\n"
//		"Usage: r_EnvCMupdateInterval 0.1\n"
//		"Default is 0.1.");
  REGISTER_CVAR3("r_EnvCMupdateInterval", CV_r_envcmupdateinterval, 0.04f, VF_DUMPTODISK,
		"Sets the interval between environmental cube map texture updates.\n"
    "Usage: r_EnvCMupdateInterval #\n"
		"Default is 0.1.");
  REGISTER_CVAR3("r_EnvTexUpdateInterval", CV_r_envtexupdateinterval, 0.001f, VF_DUMPTODISK,
		"Sets the interval between environmental 2d texture updates.\n"
		"Usage: r_EnvTexUpdateInterval 0.001\n"
		"Default is 0.001.");
  
  DefineConstIntCVar3("r_WaterReflections", CV_r_waterreflections, 1, VF_DUMPTODISK,
		"Toggles water reflections.\n"
		"Usage: r_WaterReflections [0/1]\n"
		"Default is 1 (water reflects).");

  // deprecated - we update every frame now on mgpu mode - todo: remove all related code
  DefineConstIntCVar3("r_WaterReflectionsMGPU", CV_r_waterreflections_mgpu, 0, VF_DUMPTODISK,
    "Toggles water reflections.multi-gpu support\n"
    "Usage: r_WaterReflectionsMGPU [0/1/2]\n"
    "Default is 0 (single render update), 1 (multiple render updates)");

  DefineConstIntCVar3("r_WaterReflectionsQuality", CV_r_waterreflections_quality, WATERREFLQUAL_DEFAULT_VAL, VF_DUMPTODISK,
		"Activates water reflections quality setting.\n"
		"Usage: r_WaterReflectionsQuality [0/1/2/3]\n"
		"Default is 0 (terrain only), 1 (terrain + particles), 2 (terrain + particles + brushes), 3 (everything)");

  DefineConstIntCVar3("r_WaterReflectionsUseMinOffset", CV_r_waterreflections_use_min_offset, 1, VF_DUMPTODISK,
    "Activates water reflections use min distance offset.");

  REGISTER_CVAR3("r_WaterReflectionsMinVisiblePixelsUpdate", CV_r_waterreflections_min_visible_pixels_update, 0.05f, VF_DUMPTODISK,
    "Activates water reflections if visible pixels above a certain threshold.");

  REGISTER_CVAR3("r_WaterReflectionsMinVisUpdateFactorMul", CV_r_waterreflections_minvis_updatefactormul, 20.0f, VF_DUMPTODISK,
    "Activates update factor multiplier when water mostly occluded.");  
  REGISTER_CVAR3("r_WaterReflectionsMinVisUpdateDistanceMul", CV_r_waterreflections_minvis_updatedistancemul, 10.0f, VF_DUMPTODISK,
    "Activates update distance multiplier when water mostly occluded.");  

  REGISTER_CVAR3("r_WaterCaustics", CV_r_watercaustics,1, VF_NULL,
    "Toggles under water caustics.\n"
    "Usage: r_WaterCaustics [0/1]\n"
    "Default is 1 (enabled).");  

  REGISTER_CVAR3("r_WaterCausticsDistance", CV_r_watercausticsdistance,100.0f, VF_NULL,
    "Toggles under water caustics max distance.\n"
    "Usage: r_WaterCausticsDistance\n"
    "Default is 100.0 meters");  
 
	REGISTER_CVAR3("r_WaterCausticsDeferred", CV_r_watercausticsdeferred,2, VF_NULL,
		"Toggles under water caustics deferred pass.\n"
		"Usage: r_WaterCausticsDeferred [0/1/2]\n"
		"Default is 0 (disabled). 1 - enables. 2 - enables with stencil pre-pass");  
	
  DefineConstIntCVar3("r_WaterGodRays", CV_r_water_godrays, 1, VF_NULL,
    "Enables under water god rays.\n"
    "Usage: r_WaterGodRays [0/1]\n"
    "Default is 1 (enabled).");  

	REGISTER_CVAR3("r_WaterUpdateThread", CV_r_WaterUpdateThread, 5, VF_NULL,
		"Enables water updating on separate thread (when MT supported).\n"
		"Usage: r_WaterUpdateThread [0/1/2/3/4/n]\n"
		"Default is 5 (enabled and on 5 hw thread).");  
	
	DefineConstIntCVar3("r_WaterRandomSeed", CV_r_water_random_seed, -1, VF_NULL,
    "RNG seed for waves generation; <0 disables (default)");  
	
  DefineConstIntCVar3("r_Reflections", CV_r_reflections, 1, VF_DUMPTODISK,
    "Toggles reflections.\n"
    "Usage: r_Reflections [0/1]\n"
    "Default is 1 (reflects).");

  REGISTER_CVAR3("r_ReflectionsOffset", CV_r_waterreflections_offset, 0.0f,VF_NULL,"");
    
  DefineConstIntCVar3("r_ReflectionsQuality", CV_r_reflections_quality, 3, VF_DUMPTODISK,
    "Toggles reflections quality.\n"
    "Usage: r_ReflectionsQuality [0/1/2/3]\n"
    "Default is 0 (terrain only), 1 (terrain + particles), 2 (terrain + particles + brushes), 3 (everything)");
    
  DefineConstIntCVar3("r_DetailTextures", CV_r_detailtextures, 1, VF_DUMPTODISK,
		"Toggles detail texture overlays.\n"
		"Usage: r_DetailTextures [0/1]\n"
		"Default is 1 (detail textures on).");

  DefineConstIntCVar3("r_ReloadShaders", CV_r_reloadshaders, 0, VF_CHEAT,
		"Reloads shaders.\n"
		"Usage: r_ReloadShaders [0/1]\n"
		"Default is 0. Set to 1 to reload shaders.");

  REGISTER_CVAR3("r_DetailDistance", CV_r_detaildistance, 6.0f, VF_DUMPTODISK,
		"Distance used for per-pixel detail layers blending.\n"
    "Usage: r_DetailDistance (1-20)\n"
		"Default is 6.");
  
  DefineConstIntCVar3("r_TexBindMode", CV_r_texbindmode, 0, VF_CHEAT, "");
  DefineConstIntCVar3("r_NoDrawShaders", CV_r_nodrawshaders, 0, VF_CHEAT,
		"Disable entire render pipeline.\n"
		"Usage: r_NoDrawShaders [0/1]\n"
		"Default is 0 (render pipeline enabled). Used for debugging and profiling.");
  REGISTER_CVAR3("r_NoDrawNear", CV_r_nodrawnear, 0, VF_NULL,
		"Disable drawing of near objects.\n"
		"Usage: r_NoDrawNear [0/1]\n"
		"Default is 0 (near objects are drawn).");
  REGISTER_CVAR3("r_DrawNearZRange", CV_r_DrawNearZRange, 0.12f, VF_NULL,
    "Default is 0.1.");
  REGISTER_CVAR3("r_DrawNearFarPlane", CV_r_DrawNearFarPlane, 40.0f, VF_NULL,
    "Default is 40.");
	REGISTER_CVAR3("r_DrawNearFoV", CV_r_drawnearfov, 60.0f, VF_NULL,
		"Sets the FoV for drawing of near objects.\n"
		"Usage: r_DrawNearFoV [n]\n"
		"Default is 60.");

  REGISTER_CVAR3("r_Flares", CV_r_flares, 1, VF_DUMPTODISK,
		"Toggles sunlight lens flare effect.\n"
		"Usage: r_Flares [0/1]\n"
		"Default is 1 (on).");

  REGISTER_CVAR3("r_Gamma", CV_r_gamma, 1.0f, VF_DUMPTODISK,
		"Adjusts the graphics card gamma correction (fast, needs hardware support, affects also HUD and desktop)\n"
		"Usage: r_Gamma 1.0\n"
		"1 off (default), accepted range on PS3 is 0.8 to 1.25");
  REGISTER_CVAR3("r_Brightness", CV_r_brightness, 0.5f, VF_DUMPTODISK,
		"Sets the display brightness (not supported on PS3).\n"
		"Usage: r_Brightness 0.5\n"
		"Default is 0.5.");
  REGISTER_CVAR3("r_Contrast", CV_r_contrast, 0.5f, VF_DUMPTODISK,
		"Sets the display contrast (not supported on PS3).\n"
		"Usage: r_Contrast 0.5\n"
		"Default is 0.5.");
  
  DefineConstIntCVar3("r_NoHWGamma", CV_r_nohwgamma, 0, VF_DUMPTODISK,
		"Sets renderer to ignore hardware gamma correction.\n"
		"Usage: r_NoHWGamma [0/1]\n"
		"Default is 0 (allow hardware gamma correction).");

  REGISTER_CVAR3("r_Scissor", CV_r_scissor, 1, 0, "Enables scissor test");
  REGISTER_CVAR3("r_Coronas", CV_r_coronas, CORONOAS_DEFAULT_VAL, VF_DUMPTODISK,
		"Toggles light coronas around light sources.\n"
		"Usage: r_Coronas [0/1]"
		"Default is 1 (on).");
  REGISTER_CVAR3("r_CoronaFade", CV_r_coronafade, 0.5f, VF_NULL,
		"Time fading factor of the light coronas.\n"
		"Usage: r_CoronaFade 0.5"
		"Default is 0.5.");
  REGISTER_CVAR3("r_CoronaSizeScale", CV_r_coronasizescale, 1.0f,VF_NULL,"");
  REGISTER_CVAR3("r_CoronaColorScale", CV_r_coronacolorscale, 1.0f, VF_NULL,"");
	DefineConstIntCVar3("r_Coronashafts", CV_r_coronashafts, 1, VF_DUMPTODISK,
		"Toggles light corona shafts around light sources.\n"
		"Usage: r_Coronashafts [0/1]"
		"Default is 1 (on).");
	DefineConstIntCVar3("r_LensGhostsForPointLight", CV_r_LensGhostsForPointLight, 1, VF_DUMPTODISK,
		"Toggles lens ghosts for point light sources.\n"
		"Usage: r_LensGhostForPointLight [0/1]"
		"Default is 1 (on).");
	DefineConstIntCVar3("r_LensGhostsForSun", CV_r_LensGhostsForSun, 1, VF_DUMPTODISK,
		"Toggles lens ghosts for sun.\n"
		"Usage: r_LensGhostForSun [0/1]"
		"Default is 1 (on).");

  DefineConstIntCVar3("r_wireframe", CV_r_wireframe, R_SOLID_MODE, VF_CHEAT,"");
	REGISTER_CVAR3("r_GetScreenShot", CV_r_GetScreenShot, 0, VF_NULL,
     "To capture one screenshot (variable is set to 0 after capturing)\n"
     "0=do not take a screenshot (default), 1=save a screenshot (together with .HDR if enabled), 2=save a screenshot");

  DefineConstIntCVar3("r_Character_NoDeform", CV_r_character_nodeform, 0,VF_NULL,"");

  DefineConstIntCVar3("r_Log", CV_r_log, 0, VF_CHEAT,
		"Logs rendering information to Direct3DLog.txt.\n"
		"Use negative values to log a single frame.\n"
		"Usage: r_Log +/-[0/1/2/3/4]\n"
		"	1: Logs a list of all shaders without profile info.\n"
		"	2: Log contains a list of all shaders with profile info.\n"
		"	3: Logs all API function calls.\n"
		"	4: Highly detailed pipeline log, including all passes,\n"
		"			states, lights and pixel/vertex shaders.\n"
		"Default is 0 (off). Use this function carefully, because\n"
		"log files grow very quickly.");

  DefineConstIntCVar3("r_LogVidMem", CV_r_logVidMem, 0, VF_CHEAT,
    "Logs vid mem information to VidMemLog.txt.");

  DefineConstIntCVar3("r_Stats", CV_r_stats, 0, VF_CHEAT,
		"Toggles render statistics.\n"
    "0=disabled,\n"
    "1=global render stats,\n"
    "2=print shaders for selected object,\n"
    "6=display per-instance drawcall count,\n"
    "11=print info about used RT's (switches),\n"
    "12=print info about used unique RT's,\n"
    "13=print info about cleared RT's\n"
		"Usage: r_Stats [0/1/2/3/6/11/12/13]");
#if !defined(PS3)
	REGISTER_CVAR3("r_VSync", CV_r_vsync, 0, VF_RESTRICTEDMODE|VF_DUMPTODISK,
		"Toggles vertical sync.\n"
		"0: Disabled\n"
		"1: Enabled\n"
		"2: Enabled, use asynchronous swaps on X360");
#endif
  DefineConstIntCVar3("r_PredicatedTiling", CV_r_predicatedtiling, 0, VF_REQUIRE_APP_RESTART,
		"Toggles predicated tiling mode (X360 only)\n"
    "Usage: r_PredicatedTiling [0/1]");
	DefineConstIntCVar3("r_testSplitScreen", CV_r_testSplitScreen, 0, VF_NULL,
		"Toggles split screen test mode\n"
		"Usage: r_testSplitScreen [0/1]");
	DefineConstIntCVar3("r_SplitScreenActive", CV_r_SplitScreenActive, 0, VF_NULL,
		"Activates split screen mode\n"
		"Usage: r_SplitScreenActive [0/1]");
	DefineConstIntCVar3("r_MeasureOverdraw", CV_r_measureoverdraw, 0, VF_CHEAT,
		"0=off, 1=activate special rendering mode that visualize the rendering cost per pixel by colour\n"
		"Usage: r_MeasureOverdraw [0/1]");
  REGISTER_CVAR3("r_MeasureOverdrawScale", CV_r_measureoverdrawscale, 1.5f, VF_CHEAT,"");
  DefineConstIntCVar3("r_PrintMemoryLeaks", CV_r_printmemoryleaks, 0,VF_NULL,"");
  DefineConstIntCVar3("r_ReleaseAllResourcesOnExit", CV_r_releaseallresourcesonexit, 1,VF_NULL,"");

  DefineConstIntCVar3("r_VegetationSpritesDebug",CV_r_VegetationSpritesGenDebug,0,VF_NULL,"");
	DefineConstIntCVar3("r_VegetationSpritesMaxLightingUpdates",CV_r_VegetationSpritesMaxLightingUpdates,8,VF_NULL,"");
  DefineConstIntCVar3("r_ZPassOnly",CV_r_ZPassOnly,0,VF_CHEAT,"");
  DefineConstIntCVar3("r_VegetationSpritesNoGen",CV_r_VegetationSpritesNoGen,0,VF_NULL,"");
  DefineConstIntCVar3("r_VegetationSpritesGenAlways",CV_r_VegetationSpritesGenAlways,0,VF_NULL,"");
  REGISTER_CVAR3("r_VegetationSpritesTexRes",CV_r_VegetationSpritesTexRes,128,VF_NULL,"");
  DefineConstIntCVar3("r_VegetationAlphaTestOnly",CV_r_VegetationAlphaTestOnly,0,VF_NULL,"");

	REGISTER_CVAR3("r_ShowVideoMemoryStats", CV_r_ShowVideoMemoryStats, 0,VF_NULL,"");
  REGISTER_COMMAND("r_ShowRenderTarget",&Cmd_ShowRenderTarget,VF_CHEAT, showRenderTargetHelp);

	REGISTER_CVAR3("r_BreakOnError", CV_r_BreakOnError, 1, VF_CHEAT, "calls debugbreak on illegal behaviour");

	// show texture debug routine + auto completion
	CV_r_ShowTexture = REGISTER_STRING("r_ShowTexture", "", VF_CHEAT, "Displays loaded texture - for debug purpose\n");
	gEnv->pConsole->RegisterAutoComplete( "r_ShowTexture",&g_TextureNameAutoComplete );

  DefineConstIntCVar3("r_ShowLightBounds", CV_r_ShowLightBounds, 0, VF_CHEAT,
    "Display light bounds - for debug purpose\n"
    "Usage: r_ShowLightBounds [0=off/1=on]");
	DefineConstIntCVar3("r_MergeRenderChunks", CV_r_MergeRenderChunks, 1, VF_NULL,"");

	DefineConstIntCVar3("r_UseGSParticles", CV_r_UseGSParticles, GSPARTICLES_DEFAULT_VAL, VF_NULL, 
		"Toggles use of geometry shader particles (DX11 only, changing at runtime is supported).\n"
		"Usage: r_UseGSParticles [0/1=default]");

	REGISTER_CVAR3("r_ZFightingDepthScale", CV_r_ZFightingDepthScale, 0.995f, VF_CHEAT, "Controls anti z-fighting measures in shaders (scaling homogeneous z)." );
	REGISTER_CVAR3("r_ZFightingExtrude", CV_r_ZFightingExtrude, 0.001f, VF_CHEAT, "Controls anti z-fighting measures in shaders (extrusion along normal in world units)." );

	DefineConstIntCVar3("r_UseSRGB", CV_r_useSRGB, 1, VF_REQUIRE_APP_RESTART, "Enables sRGB texture reads / framebuffer writes.\n"
		"Usage: r_UseSRGB [0=off/1=lighting is computed in linear space]");
	ICVar* pCV_r_TexelsPerMeter = REGISTER_CVAR3("r_TexelsPerMeter", CV_r_TexelsPerMeter, 0, 0, 
		"Enables visualization of the color coded \"texels per meter\" ratio for objects in view.\n"
		"The checkerboard pattern displayed represents the mapping of the assigned diffuse\n"
		"texture onto the object's uv space. One block in the pattern represents 8x8 texels.\n"
		"Usage: r_TexelsPerMeter [n] (where n is the desired number of texels per meter; 0 = off)");

	if (pCV_r_TexelsPerMeter)
		pCV_r_TexelsPerMeter->SetOnChangeCallback(OnChange_CV_r_TexelsPerMeter);

	REGISTER_CVAR3("r_enableAltTab", CV_r_enableAltTab, 1, VF_NULL,
		"Toggles alt tabbing in and out of fullscreen when the game is not in devmode.\n"
		"Usage: r_enableAltTab [toggle]\n"
		"Notes: Should only be added to system.cfg and requires a restart");

	REGISTER_CVAR3("r_StereoDevice", CV_r_StereoDevice, 100, VF_REQUIRE_APP_RESTART|VF_DUMPTODISK,
		"Sets stereo device (only possible before app start)\n"
		"Usage: r_StereoDevice [0/1/2/3/4]\n"
		"0: No stereo support (default)\n"
		"1: Frame compatible formats (side-by-side, interlaced, anaglyph)\n"
		"2: HDMI 1.4 (PS3 only)\n"
		"3: Stereo driver (PC only, NVidia or AMD)\n"
		"4: Dualhead (PC only, two projectors or iZ3D screen)\n"
		"100: Auto-detect device for platform");
	
	REGISTER_CVAR3("r_StereoMode", CV_r_StereoMode, 0, VF_DUMPTODISK,
		"Sets stereo rendering mode.\n"
		"Usage: r_StereoMode [0=off/1/2]\n"
		"1: Dual rendering\n"
		"2: Post Stereo\n");




	REGISTER_CVAR3("r_StereoOutput", CV_r_StereoOutput, 0, VF_DUMPTODISK,
		"Sets stereo output. Output depends on the stereo monitor\n"
		"Usage: r_StereoOutput [0=off/1/2/3/4/5/6]\n"
		"0: Standard\n"
		"1: IZ3D\n"
		"2: Checkerboard (not supported on X360)\n"
		"3: Above and Below (not supported)\n"
		"4: Side by Side\n"
		"5: Line by Line (Interlaced)\n"
		"6: Anaglyph\n");




	REGISTER_CVAR3("r_StereoFlipEyes", CV_r_StereoFlipEyes, 0, VF_DUMPTODISK,
		"Flip eyes in stereo mode.\n"
		"Usage: r_StereoFlipEyes [0=off/1=on]\n"
		"0: don't flip\n"
		"1: flip\n");

	REGISTER_CVAR3("r_StereoStrength", CV_r_StereoStrength, 1.0f, VF_DUMPTODISK,
		"Multiplier which influences the strength of the stereo effect.");
	
	REGISTER_CVAR3("r_StereoEyeDist", CV_r_StereoEyeDist, 0.02f, VF_DUMPTODISK,
		"Maximum separation between stereo images in percentage of the screen.");

	REGISTER_CVAR3("r_StereoScreenDist", CV_r_StereoScreenDist, 0.25f, VF_DUMPTODISK,
		"Distance to plane where stereo parallax converges to zero.");

	REGISTER_CVAR3("r_StereoNearGeoScale", CV_r_StereoNearGeoScale, 0.65f, VF_DUMPTODISK,
		"Scale for near geometry (weapon) that gets pushed into the screen");

	REGISTER_CVAR3("r_StereoHudScreenDist", CV_r_StereoHudScreenDist, 0.5f, VF_DUMPTODISK,
		"Distance to plane where hud stereo parallax converges to zero.\n"
		"If not zero, HUD needs to be rendered two times.");

	REGISTER_CVAR3("r_StereoGammaAdjustment", CV_r_StereoGammaAdjustment, 0.12f, VF_DUMPTODISK,
		"Additional adjustment to the graphics card gamma correction when Stereo is enabled.\n"
		"Usage: r_StereoGammaAdjustment [offset]"
		"0: off");

	const int DEVICE_WIDTH	=	1152;
	const int	DEVICE_HEIGHT	=	720;

	REGISTER_CVAR3("r_ConsoleBackbufferWidth", CV_r_ConsoleBackbufferWidth,DEVICE_WIDTH, VF_DUMPTODISK,
		"console specific backbuffer resolution - width");
	REGISTER_CVAR3("r_ConsoleBackbufferHeight", CV_r_ConsoleBackbufferHeight,DEVICE_HEIGHT, VF_DUMPTODISK,
		"console specific backbuffer resolution - height");

  REGISTER_CVAR3("r_ConditionalRendering", CV_r_ConditionalRendering, 0, VF_NULL, "Enables conditional rendering .");











	REGISTER_CVAR3("r_CustomResMaxSize", CV_r_CustomResMaxSize, 4096, VF_NULL, "Maximum resolution of custom resolution rendering");
	REGISTER_CVAR3("r_CustomResWidth", CV_r_CustomResWidth, 0, VF_NULL, "Width of custom resolution rendering");
	REGISTER_CVAR3("r_CustomResHeight", CV_r_CustomResHeight, 0, VF_NULL, "Height of custom resolution rendering");
	REGISTER_CVAR3("r_CustomResPreview", CV_r_CustomResPreview, 1, VF_NULL, "Enable/disable preview of custom resolution rendering in viewport"
		"(0 - no preview, 1 - scaled to match viewport, 2 - custom resolution clipped to viewport");
	REGISTER_CVAR3("r_Supersampling", CV_r_Supersampling, 1, VF_NULL, "Use supersampled antialiasing"
		"(1 - 1x1 no SSAA, 2 - 2x2, 3 - 3x3 ...)");
	REGISTER_CVAR3("r_SupersamplingFilter", CV_r_SupersamplingFilter, 0, VF_NULL, "Filter method to use when resolving supersampled output"
		"\n0 - Box filter"
		"\n1 - Tent filter"
		"\n2 - Gaussian filter"
		"\n3 - Lanczos filter");




















#if !defined (XENON) && !defined(PS3) && !defined(CAFE) && !defined(NULL_RENDERER)
  REGISTER_COMMAND("r_PrecacheShaders", &ShadersPrecache,VF_NULL,"");
	REGISTER_COMMAND("r_PrecacheShaderList", &ShadersPrecacheList,VF_NULL,"");
  REGISTER_COMMAND("r_StatsShaders", &ShadersStats,VF_NULL,"");
  REGISTER_COMMAND("r_StatsShaderList", &ShadersStatsList,VF_NULL,"");
  REGISTER_COMMAND("r_OptimiseShaders", &ShadersOptimise,VF_NULL,"");
  REGISTER_COMMAND("r_MergeShaders", &ShadersMerge,VF_CHEAT,"");
  REGISTER_COMMAND("r_PrecacheShadersLevels", &ShadersPrecacheLevels,VF_NULL,"");
#endif

	DefineConstIntCVar3("r_TextureCompressor", CV_r_TextureCompressor, 1, VF_DUMPTODISK,
		"Defines which texture compressor is used (fallback is DirectX)\n"
		"Usage: r_TextureCompressor [0/1]\n"
		"0 uses nvDXT, 1 uses Squish if possible");

	REGISTER_CVAR3("r_FogDepthTest", CV_r_FogDepthTest, -0.0005f, VF_NULL,
		"Enables per-pixel culling for deferred volumetric fog pass.\n"
		"Fog computations for all pixels closer than a given depth value will be skipped.\n"
		"Usage: r_FogDepthTest z with...\n"
		"  z = 0, culling disabled\n"
		"  z > 0, fixed linear world space culling depth\n"
		"  z < 0, optimal culling depth will be computed automatically based on camera direction and fog settings");

#if defined(VOLUMETRIC_FOG_SHADOWS)
	REGISTER_CVAR3("r_FogShadows", CV_r_FogShadows, 0, VF_NULL, "Enables deferred volumetric fog shadows");
#endif

	DefineConstIntCVar3("r_Scratches", CV_r_Scratches, 2, VF_CHEAT,
		"Sets fullscreen scratches post-process effect usage.\n"
		"Usage: r_Scratches [0/1/2]\n"
		"0: force off\n"
		"1: force on \n"
		"2: on in game-mode only (default)\n"
		"3: as 2, but independent of sunshafts or sun postion");

	DefineConstIntCVar3("r_HUDHitEffect", CV_r_HUDHitEffect, 4, VF_CHEAT,
		"Enable HUD Hit Effects.\n"
		"Usage: r_HUDHitEffect [0/1]\n"
		"0: force off\n"
		"1: on (default (rectangles)\n"
		"2: on (different border rendering (trapezoids))\n"
		"3: on (alternating border rendering methods)\n"
		"4: on (fullscreen rendering)");

	DefineConstIntCVar3("r_RainDropsEffect", CV_r_RainDropsEffect, 1, VF_CHEAT,
		"Enable RainDrops effect.\n"
		"Usage: r_RainDropEffect [0/1/2]\n"
		"0: force off\n"
		"1: on (default)\n"
		"2: on (forced)");

	DefineConstIntCVar3("r_RefractionPartialResolves", CV_r_RefractionPartialResolves, 2, VF_NULL,
		"Do a partial screen resolve before refraction\n"
		"Usage: r_RefractionPartialResolves [0/1]\n"
		"0: disable \n"
		"1: enable conservativley (non-optimal)\n"
		"2: enable (default)");

	DefineConstIntCVar3("r_Batching", CV_r_Batching, 1, VF_NULL,
		"Enable/disable render items buching\n"
		"Usage: r_Batching [0/1]\n");

	REGISTER_CVAR3("r_FlashMatTexResQuality", CV_r_FlashMatTexResQuality, 1.0f, VF_NULL,
		"Texture resolution quality of flash materials.\n"
		"Only used if flash asset is tagged CE_HQR!");

	REGISTER_CVAR3("r_DynTexSourceSharedRTWidth", CV_r_DynTexSourceSharedRTWidth, 256, VF_NULL,
		"Width of shared RT for dynamic texture sources.");

	REGISTER_CVAR3("r_DynTexSourceSharedRTHeight", CV_r_DynTexSourceSharedRTHeight, 256, VF_NULL,
		"Height of shared RT for dynamic texture sources.");

	REGISTER_CVAR3("r_DynTexSourceUseSharedRT", CV_r_DynTexSourceUseSharedRT, 1, VF_REQUIRE_LEVEL_RELOAD,
		"Defines if dynamic flash textures are rendered into shared RT\n"
		"Usage: r_DynTexSourceUseSharedRT [0/1].\n"
		"0: Use Unique RT for each dynamic flash texture (with alpha support)\n"
		"1: Use Shared RT for all dynamic flash textures (no alpha support!)\n"
		"Disabled by default. Requires level reload to change.");

#if !defined(_RELEASE)
	REGISTER_CVAR3("r_PS3AllocFailureResource", CV_r_PS3AllocFailureResource, 255, VF_NULL,
		"Bit mask to indicate which kinds of RSX allocations should be considered when simulating an allocation failure via r_PS3AllocFailureRate.\n"
		"Usage: r_PS3AllocFailureResource bitMask. bitMask is a logical combination of the values below:\n"
		"       Layout       = 0x01\n"
		"       Blob         = 0x02\n"
		"       Texture1D    = 0x04\n"
		"       Texture2D    = 0x08\n"
		"       Texture3D    = 0x10\n"
		"       VertexBuffer = 0x20\n"
		"       IndexBuffer  = 0x40\n"
		"       ConstBuffer  = 0x80");

	REGISTER_CVAR3("r_PS3AllocFailureRate", CV_r_PS3AllocFailureRate, 0, VF_NULL,
		"Forces every n-th RSX allocation to fail. See r_PS3AllocFailureResource.\n"
		"Usage: r_PS3AllocFailureRate n\n"
		"       r_PS3AllocFailureRate 0 to turn it off");
#endif

	// more details: http://en.wikipedia.org/wiki/Overscan
	// Microsoft's Xbox game developer guidelines recommend using 85 percent of the screen width and height,[7] or a title safe area of 7.5% per side.
	REGISTER_COMMAND("r_OverscanBorders", &cmd_OverscanBorders, VF_NULL,
		"Changes the size of the overscan borders for the left/right and top/bottom\n"
		"of the screen for adjusting the title safe area. This is for logo placements\n"
		"and text printout to account for the TV overscan and is mostly needed for consoles.\n"
		"If only one value is specified, the overscan borders for left/right and top/bottom\n"
		"are set simultaneously, but you may also specify different percentages for left/right\n"
		"and top/bottom.\n"
		"Usage: r_OverscanBorders [0..25]\n"
		"       r_OverscanBorders [0..25] [0..25]\n"
		"Default is 0=off, >0 defines the size of the overscan borders for left/right\n"
		"or top/bottom as percentages of the whole screen size (e.g. 7.5).");

#if defined(ENABLE_RENDER_AUX_GEOM)
#	if !defined(_RELEASE)
	const int defValAuxGeomEnable = 1;
#else
	const int defValAuxGeomEnable = 0;
#endif
	REGISTER_CVAR2("r_enableAuxGeom", &CV_r_enableauxgeom, defValAuxGeomEnable, VF_REQUIRE_APP_RESTART, "Enables aux geometry rendering.");
#endif













  m_cClearColor = ColorF(0,0,0,128.0f/255.0f);		// 128 is default GBuffer value
  m_LogFile = NULL;
	m_pDefaultFont = NULL;
  m_TexGenID = 1;
  m_VSync = CV_r_vsync;
  m_Features = 0;
#if !defined(XENON) && !defined(PS3)
	m_bNVLibInitialized=false;
	m_bDriverHasActiveMultiGPU=false;
#endif

  //init_math();

	for(uint32 id=0;id<RT_COMMAND_BUF_COUNT;++id)
		m_RP.m_TI[id].m_nFrameID = (unsigned short)-2;

  m_bPauseTimer=0;
  m_fPrevTime=-1.0f;

//  m_RP.m_ShaderCurrTime = 0.0f;

  m_CurFontColor = Col_White;

  m_bUseHWSkinning = CV_r_usehwskinning != 0;
  m_bWaterCaustics = CV_r_watercaustics != 0;

	m_bSwapBuffers = true;
	for(uint32 id=0;id<RT_COMMAND_BUF_COUNT;++id)
		m_RP.m_TI[id].m_FS.m_bEnable = true;

#if defined(_DEBUG) && defined(WIN32)
  if (CV_r_printmemoryleaks)
  {
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  }
#endif

  m_bUseZpass = CV_r_usezpass != 0;  

	m_cloudShadowTexId = 0;
	m_cloudShadowSpeed = Vec3(0,0,0);
	m_cloudShadowTiling = 1;
	m_cloudShadowInvert = false;
	m_cloudShadowBrightness = 1;

#ifndef EXCLUDE_SCALEFORM_SDK
	m_pSFDrawParams = 0;
#endif

  m_nGPUs = 1;

  //assert(!(FOB_MASK_AFFECTS_MERGING & 0xffff));
  //assert(sizeof(CRenderObject) == 256);
#if !defined(PLATFORM_64BIT) && !defined(PS3) && !defined(CAFE)
  STATIC_CHECK(sizeof(CRenderObject) == 128, CRenderObject);
#endif
  STATIC_CHECK(!(FOB_MASK_AFFECTS_MERGING & 0xffff), FOB_MASK_AFFECTS_MERGING);

	if (!g_pSDynTexture_PoolAlloc) 
		g_pSDynTexture_PoolAlloc = new SDynTexture_PoolAlloc(0, stl::FHeap().FreeWhenEmpty(true));

  //m_RP.m_VertPosCache.m_nBufSize = 500000 * sizeof(Vec3);
  //m_RP.m_VertPosCache.m_pBuf = new byte [gRenDev->m_RP.m_VertPosCache.m_nBufSize];

  m_pDefaultMaterial = NULL;
  m_pTerrainDefaultMaterial = NULL;

	m_ViewMatrix.SetIdentity();
	m_CameraMatrix.SetIdentity();
	for(int i=0; i<RT_COMMAND_BUF_COUNT; ++i)
	{
		m_CameraZeroMatrix[i].SetIdentity();
	//	m_CameraMatrixPrev[i][0].SetIdentity();
//		m_CameraMatrixPrev[i][1].SetIdentity();
	}
	
	m_CameraMatrixPrev.SetIdentity();
	m_CameraProjMatrixPrev.SetIdentity();
	m_CameraProjMatrixPrevAvg.SetIdentity();

	m_ProjMatrix.SetIdentity();
	m_TranspOrigCameraProjMatrix.SetIdentity();
  m_CameraProjMatrix.SetIdentity();  
	m_CameraProjZeroMatrix.SetIdentity();
	m_InvCameraProjMatrix.SetIdentity();
  m_IdentityMatrix.SetIdentity();

	m_vProjMatrixSubPixoffset = Vec2(0.0f, 0.0f);
	m_vSegmentedWorldOffset = Vec3(ZERO);

  //m_RP.m_oldOcclusionCamera.SetIdentity();
  m_RP.m_newOcclusionCameraProj.SetIdentity();
  m_RP.m_newOcclusionCameraView.SetIdentity();

	for (int i = 0; i < CULLER_MAX_CAMS; i++)
	{
		m_RP.m_OcclusionCameraBuffer[i].SetIdentity();
#ifdef CULLER_DEBUG
		m_RP.m_OcclusionCameraBufferID[i] = -1;
#endif
	}

	m_RP.m_nZOcclusionBufferID =-1;

	m_RP.m_nCurrResolveBounds[0] = m_RP.m_nCurrResolveBounds[1] = m_RP.m_nCurrResolveBounds[2] = m_RP.m_nCurrResolveBounds[3] = 0;

	for (int i = 0; i < SIZEOF_ARRAY(m_TempMatrices); i++)
		for (int j = 0; j < SIZEOF_ARRAY(m_TempMatrices[0]); j++)
			m_TempMatrices[i][j].SetIdentity();

  CParserBin::m_bParseFX = true;
  //CParserBin::m_bEmbeddedSearchInfo = false;
  if (gEnv->IsEditor())
    CParserBin::m_bEditable = true;
#ifndef CONSOLE_CONST_CVAR_MODE
	CV_e_DebugTexelDensity = 0;
#endif
	m_nFlushAllPendingTextureStreamingJobs = 0;
	m_fTexturesStreamingGlobalMipFactor = 0.f;

	m_fogCullDistance = 0.0f;

	m_pDebugRenderNode = NULL;

	m_bCollectDrawCallsInfo = false;
	m_bCopyScreenToBackBuffer = false;

	m_nMeshPoolTimeoutCounter = nMeshPoolMaxTimeoutCounter;

	m_pTextureManager = new CTextureManager;

	CMeshSubSetIndicesTask::CreateThreadPool();

  m_pRT = new SRenderThread;
	m_pRT->StartRenderThread();

#if SUPPORT_RENDER_TO_CONTROLLER
	m_renderToScreenOnController = NULL;
#endif

	// on console some float values in vertex formats can be 16 bit
	iLog->Log("CRenderer sizeof(Vec2f16)=%d sizeof(Vec3f16)=%d",(int32)sizeof(Vec2f16),(int32)sizeof(Vec3f16));
	CRenderMesh::Initialize();
}

CRenderer::~CRenderer()
{
	//Code now moved to Release()
}

//////////////////////////////////////////////////////////////////////////
void CRenderer::PostInit()
{
	//////////////////////////////////////////////////////////////////////////
	// Initialize the shader system
	//////////////////////////////////////////////////////////////////////////
	m_cEF.mfPostInit();

	//////////////////////////////////////////////////////////////////////////
	// Load internal renderer font.
	//////////////////////////////////////////////////////////////////////////
	if (gEnv->pCryFont)
	{
		m_pDefaultFont = gEnv->pCryFont->GetFont("default");
		if (!m_pDefaultFont)
			CryWarning(VALIDATOR_MODULE_SYSTEM,VALIDATOR_ERROR, "Error getting default font");
	}

	// load all default textures
	if (!m_bShaderCacheGen && m_pTextureManager)
		m_pTextureManager->PreloadDefaultTextures();

#if SUPPORT_RENDER_TO_CONTROLLER
	SetRenderToScreenOnController(new CRenderToDRC());
	m_pRT->RC_InitialiseControllerRenderer();
#endif

}

//////////////////////////////////////////////////////////////////////////

#define INTRO_MOVIES_PAK "_fastload/IntroMovies.pak"

void CRenderer::StartRenderIntroMovies()
{
	assert(m_pIntroMovieRenderer == 0);

	// Make sure intro pak is valid and excistion else don't bother rendering them
	if (!gEnv->pCryPak->OpenPack(PathUtil::GetGameFolder(), INTRO_MOVIES_PAK, 
		ICryPak::FLAGS_PAK_IN_MEMORY))
		return;

	gEnv->pCryPak->LoadPakToMemory(INTRO_MOVIES_PAK, true);
		
	m_pIntroMovieRenderer = new CIntroMovieRenderer;
	m_pIntroMovieRenderer->Initialize();

	StartLoadtimeFlashPlayback(m_pIntroMovieRenderer);
}

void CRenderer::StopRenderIntroMovies(bool bWaitForFinished)
{
	if (m_pIntroMovieRenderer == 0)
		return;

	if (bWaitForFinished)
	{
		m_pIntroMovieRenderer->WaitForCompletion();
	}

	StopLoadtimeFlashPlayback();
	SAFE_DELETE(m_pIntroMovieRenderer);

	// we don't need the intro movies in memory anymore
	gEnv->pCryPak->LoadPakToMemory(INTRO_MOVIES_PAK, 0, false);
	gEnv->pCryPak->ClosePack(INTRO_MOVIES_PAK, 0);
}

bool CRenderer::IsRenderingIntroMovies() const
{
	return (m_pIntroMovieRenderer != NULL);
}

//////////////////////////////////////////////////////////////////////////

void CRenderer::Release()
{
	// Reminder for Andrey/AntonKap: this needs to be properly handled
	//SAFE_DELETE(g_pSDynTexture_PoolAlloc)
	//g_pSDynTexture_PoolAlloc = NULL;

#if !defined (_RELEASE)
  ClearTexturePoolAllocationList(m_RP.m_nFillThreadID);
  ClearTexturePoolAllocationList(m_RP.m_nProcessThreadID);
#endif

	CRenderMesh::ShutDown();

	gRenDev = NULL;
}

//////////////////////////////////////////////////////////////////////
void CRenderer::AddListener(IRendererEventListener *pRendererEventListener)
{
	stl::push_back_unique(m_listRendererEventListeners,pRendererEventListener);
}

//////////////////////////////////////////////////////////////////////
void CRenderer::RemoveListener(IRendererEventListener *pRendererEventListener)
{
	stl::find_and_erase(m_listRendererEventListeners,pRendererEventListener);
}

//////////////////////////////////////////////////////////////////////
/*bool CRenderer::FindImage(CImage *image)
{
	for (ImageIt i=m_imageList.begin();i!=m_imageList.end();i++)
	{
		CImage *ci=(*i);

		if (ci==image) 
			return (true);
	} //i

	return (false);
} */

//////////////////////////////////////////////////////////////////////
/*CImage *CRenderer::FindImage(const char *filename)
{

	ImageIt istart=m_imageList.begin();
	ImageIt iend=m_imageList.end();

	for (ImageIt i=m_imageList.begin();i!=iend;i++)
	{
		CImage *ci=(*i);

		if (stricmp(ci->GetName(),filename)==0) 
			return (ci);
	} //i

	return (NULL);
} */

//////////////////////////////////////////////////////////////////////
/*void CRenderer::AddImage(CImage *image)
{
	m_imageList.push_back(image);
} */

//////////////////////////////////////////////////////////////////////
//void CRenderer::ShowFps(const char *command/* =NULL */)
/*{
	if (!command) 
		return;
	if (stricmp(command,"true")==0) 
		m_showfps=true;
	else
	if (stricmp(command,"false")==0) 
		m_showfps=false;	
	else
	  iConsole->Help("ShowFps");
} */

//////////////////////////////////////////////////////////////////////
void CRenderer::TextToScreenColor(int x, int y, float r, float g, float b, float a, const char * format, ...)
{
//  if(!cVars->e_text_info)
  //  return;

  char buffer[512];
  va_list args;
  va_start(args, format);
	if (vsnprintf(buffer,sizeof(buffer),format, args) == -1)
		buffer[sizeof(buffer)-1] = 0;
  va_end(args);

  WriteXY((int)(8*x), (int)(6*y), 1, 1, r,g,b,a, buffer);
}

//////////////////////////////////////////////////////////////////////
void CRenderer::TextToScreen(float x, float y, const char * format, ...)
{
//  if(!cVars->e_text_info)
  //  return;

  char buffer[512];
  va_list args;
  va_start(args, format);
	if (vsnprintf(buffer,sizeof(buffer),format, args) == -1)
		buffer[sizeof(buffer)-1] = 0;
  va_end(args);

  WriteXY((int)(8*x), (int)(6*y), 1, 1, 1,1,1,1, buffer);
}

//////////////////////////////////////////////////////////////////////////
void CRenderer::Draw2dText(float posX, float posY, const char* pStr, const SDrawTextInfo& ti)
{
	Draw2dTextWithDepth(posX, posY, 1.0f, pStr, ti);
}

//////////////////////////////////////////////////////////////////////////
void CRenderer::Draw2dTextWithDepth(float posX, float posY, float posZ, const char* pStr, const SDrawTextInfo& ti)
{
	IF (!m_pDefaultFont, 0)
		return;

	IFFont* pFont = m_pDefaultFont;

	const float r = CLAMP(ti.color[0], 0.0f, 1.0f);
	const float g = CLAMP(ti.color[1], 0.0f, 1.0f);
	const float b = CLAMP(ti.color[2], 0.0f, 1.0f);
	const float a = CLAMP(ti.color[3], 0.0f, 1.0f);

	STextDrawContext ctx;
	ctx.SetColor(ColorF(r, g, b, a));
	ctx.SetCharWidthScale(1.0f);
	ctx.EnableFrame((ti.flags & eDrawText_Framed) != 0);

	if (ti.flags & eDrawText_Monospace)
	{
		if (ti.flags & eDrawText_FixedSize)
			ctx.SetSizeIn800x600(false);
		ctx.SetSize(Vec2(UIDRAW_TEXTSIZEFACTOR * ti.xscale, UIDRAW_TEXTSIZEFACTOR * ti.yscale));
		ctx.SetCharWidthScale(0.5f);
		ctx.SetProportional(false);

		if (ti.flags & eDrawText_800x600)
			ScaleCoordInternal(posX, posY);
	}
	else if (ti.flags & eDrawText_FixedSize)
	{
		ctx.SetSizeIn800x600(false);
		ctx.SetSize(Vec2(UIDRAW_TEXTSIZEFACTOR * ti.xscale, UIDRAW_TEXTSIZEFACTOR * ti.yscale));
		ctx.SetProportional(true);

		if (ti.flags & eDrawText_800x600)
			ScaleCoordInternal(posX, posY);
	}
	else
	{
		ctx.SetSizeIn800x600(true);
		ctx.SetProportional(false);
		ctx.SetCharWidthScale(0.5f);
		ctx.SetSize(Vec2(UIDRAW_TEXTSIZEFACTOR * ti.xscale, UIDRAW_TEXTSIZEFACTOR * ti.yscale));
	}

	// align left/right/center
	if (ti.flags & (eDrawText_Center | eDrawText_CenterV | eDrawText_Right))
	{
		Vec2 textSize = pFont->GetTextSize(pStr, true, ctx);
		if (ti.flags & eDrawText_Center)
			posX -= textSize.x * 0.5f;
		else if (ti.flags & eDrawText_Right)
			posX -= textSize.x;

		if (ti.flags & eDrawText_CenterV)
			posY -= textSize.y * 0.5f;
	}

	pFont->DrawString(posX, posY, posZ, pStr, true, ctx);
}

void CRenderer::PrintToScreen(float x, float y, float size, const char *buf)
{
  SDrawTextInfo ti;
  ti.xscale = size*0.5f/8;
  ti.yscale = size*1.f/8;
  ti.color[0] = 1; ti.color[1] = 1; ti.color[2] = 1; ti.color[3] = 1;
	ti.flags = eDrawText_800x600|eDrawText_2D;
  Draw2dText( x,y,buf,ti );
}

void CRenderer::WriteXY( int x, int y, float xscale, float yscale, float r, float g, float b, float a, const char *format, ...)
{
  //////////////////////////////////////////////////////////////////////
  // Write a string to the screen
  //////////////////////////////////////////////////////////////////////

  va_list args;

  char buffer[512];

  // Check for the presence of a D3D device
  // Format the string
  va_start(args, format);
	if (vsnprintf(buffer,sizeof(buffer),format, args) == -1)
		buffer[sizeof(buffer)-1] = 0;
  va_end(args);

  SDrawTextInfo ti;
  ti.xscale = xscale;
  ti.yscale = yscale;
  ti.color[0] = r;
  ti.color[1] = g;
  ti.color[2] = b;
  ti.color[3] = a;
	ti.flags = eDrawText_800x600|eDrawText_2D;
  Draw2dText( (float)x,(float)y,buffer,ti );
}

//////////////////////////////////////////////////////////////////////////
void CRenderer::DrawTextQueued( Vec3 pos,SDrawTextInfo &ti,const char *text )
{
	int nT = m_pRT->GetThreadList();
	if (text && !gEnv->IsDedicated())
	{
		// ti.yscale is currently ignored, input struct can be refactored

		ColorB col(ColorF(ti.color[0],ti.color[1],ti.color[2],ti.color[3]));

		m_TextMessages[nT].PushEntry_Text(pos,col,ti.xscale,ti.flags,text);
	}
}

//////////////////////////////////////////////////////////////////////////
void CRenderer::DrawTextQueued( Vec3 pos,SDrawTextInfo &ti,const char *format,va_list args )
{
	int nT = m_pRT->GetThreadList();
	if (format && !gEnv->IsDedicated())
	{
		char str[256];

		vsnprintf_s(str,sizeof(str),sizeof(str)-1,format, args);
		str[sizeof(str)-1] = 0;

		// ti.yscale is currently ignored, input struct can be refactored

		ColorB col(ColorF(ti.color[0],ti.color[1],ti.color[2],ti.color[3]));

		m_TextMessages[nT].PushEntry_Text(pos,col,ti.xscale,ti.flags,str);
	}
}

//////////////////////////////////////////////////////////////////////
void CRenderer::DrawLabelImage(const Vec3 &vPos,float fImageSize,int nTextureId)
{
  int nT = m_pRT->GetThreadList();

	m_TextMessages[nT].PushEntry_Texture(vPos,nTextureId,fImageSize);
}

//////////////////////////////////////////////////////////////////////
void CRenderer::FlushTextMessages()
{
	ASSERT_IS_MAIN_THREAD(m_pRT)

	if(!m_TextMessages[m_RP.m_nFillThreadID].empty())
	  m_pRT->RC_FlushTextMessages();
}

void CRenderer::RT_FlushTextMessages()
{
  FUNCTION_PROFILER_FAST( GetISystem(),PROFILE_RENDERER,g_bProfilerEnabled );

  int nT = m_RP.m_nProcessThreadID;

	if (gEnv->IsDedicated() || (m_pRT && m_pRT->m_eVideoThreadMode != SRenderThread::eVTM_Disabled))
	{
		m_TextMessages[nT].Clear();
		return;
	}
	
	//if (GetIRenderAuxGeom())
	//	GetIRenderAuxGeom()->Flush();

  EnableFog(false);
	int vx,vy,vw,vh;
	GetViewport( &vx,&vy,&vw,&vh );

	while(const CTextMessages::CTextMessageHeader *pEntry = m_TextMessages[nT].GetNextEntry())
	{
		const CTextMessages::SText *pText = pEntry->CastTo_Text();
		const CTextMessages::STexture *pTexture = pEntry->CastTo_Texture();

		Vec3 vPos(0,0,0);
		int nDrawFlags = 0;
		const char *szText = 0;
		Vec4 vColor(1,1,1,1);
		float fSize=0;

		if(pText)
		{
			nDrawFlags = pText->m_nDrawFlags;
			szText = pText->GetText();
			vPos = pText->m_vPos;
			vColor = pText->m_Color.toVec4()*1.0f/255.0f;
			fSize = pText->m_fFontSize;
		}
		else if(pTexture)
		{
			vPos = pTexture->m_vPos;
			fSize = pTexture->m_fImageSize; 
		}

		bool b800x600 = (nDrawFlags & eDrawText_800x600) != 0;

		float fMaxPosX = 100.0f;
		float fMaxPosY = 100.0f;

		if(!b800x600)
		{
			fMaxPosX = (float)vw;
			fMaxPosY = (float)vh;
		}

    float sx,sy,sz;

		if (!(nDrawFlags & eDrawText_2D))
		{
			float fDist = 1; //GetDistance(pTextInfo->pos,GetCamera().GetPosition());
      
			float K = GetCamera().GetFarPlane()/fDist;
      if(fDist>GetCamera().GetFarPlane()*0.5)
        vPos = GetCamera().GetPosition() + K*(vPos - GetCamera().GetPosition());

			ProjectToScreen( vPos.x, vPos.y, vPos.z, &sx, &sy, &sz );
		}
		else
		{
			if (b800x600)
			{
				// Make 2D coords in range 0-100
				sx = (vPos.x) / vw * 100;
				sy = (vPos.y) / vh * 100;
			}
			else
			{
				sx = vPos.x;
				sy = vPos.y;
			}

			sz = vPos.z;
		}

    if(sx>=0 && sx<=fMaxPosX)
    if(sy>=0 && sy<=fMaxPosY)
    if(sz>=0 && sz<=1)
    {
      // calculate size
      float sizeX;
			float sizeY;
			if (nDrawFlags & eDrawText_FixedSize)
			{
				sizeX = fSize;
				sizeY = fSize;
        //sizeX = pTextInfo->font_size * 800.0f/vw;
				//sizeY = pTextInfo->font_size * 500.0f/vh;
			}
      else
			{
        sizeX = sizeY = (1.0f-(float)(sz))*32.f*fSize;
				sizeX *= 0.5f;
			}

			if (szText)
			{
	      // print
				SDrawTextInfo ti;
				ti.flags = nDrawFlags;
				ti.color[0] = vColor.x;
				ti.color[1] = vColor.y;
				ti.color[2] = vColor.z;
				ti.color[3] = vColor.w;
				ti.xscale = sizeX;
				ti.yscale = sizeY;
				if (nDrawFlags & eDrawText_DepthTest)
				{
					sz = 1.0f - 2.0f * sz;
				}
				else
				{
					sz = 1.0f;
				}
				if (b800x600)
					Draw2dTextWithDepth( 0.01f*800*sx,0.01f*600*sy,sz,szText,ti );
				else
					Draw2dTextWithDepth( sx,sy,sz,szText,ti );
			}			

			if(pTexture)
			if(pTexture->m_nTextureID>=0)
			{
        SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST);
        SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
				SetTexture(pTexture->m_nTextureID);				

			  Matrix44	mat;
			  GetModelViewMatrix(mat.GetData());
				Vec3 vRight( mat(0,0), mat(1,0), mat(2,0));
				Vec3 vUp( mat(0,1), mat(1,1), mat(2,1) ); 				

				DrawQuad(vRight,vUp,vPos,2);		
        SetState(GS_DEPTHWRITE);
			}
		}
	}

	m_TextMessages[nT].Clear();
}

#if !defined(PS3) && !defined(LINUX) && !defined(CAFE)
#pragma pack (push)
#pragma pack (1)
typedef struct
{
  unsigned char  id_length, colormap_type, image_type;
  unsigned short colormap_index, colormap_length;
  unsigned char  colormap_size;
  unsigned short x_origin, y_origin, width, height;
  unsigned char  pixel_size, attributes;
}	TargaHeader_t;
#pragma pack (pop)
#else
typedef struct
{
	unsigned char  id_length, colormap_type, image_type;
	unsigned short colormap_index _PACK, colormap_length _PACK;
	unsigned char  colormap_size;
	unsigned short x_origin _PACK, y_origin _PACK, width _PACK, height _PACK;
	unsigned char  pixel_size, attributes;
}	TargaHeader_t;
#endif

bool	CRenderer::SaveTga(unsigned char *sourcedata,int sourceformat,int w,int h,const char *filename,bool flip) const
{
  //assert(0);
//  return CImage::SaveTga(sourcedata,sourceformat,w,h,filename,flip);
	
	if (flip)
	{
		int size=w*(sourceformat/8);
		unsigned char *tempw=new unsigned char [size];
		unsigned char *src1=sourcedata;		
		unsigned char *src2=sourcedata+(w*(sourceformat/8))*(h-1);
		for (int k=0;k<h/2;k++)
		{
			memcpy(tempw,src1,size);
			memcpy(src1,src2,size);
			memcpy(src2,tempw,size);
			src1+=size;
			src2-=size;
		}
		delete [] tempw;
	}
	

	unsigned char *oldsourcedata=sourcedata;

	if (sourceformat==FORMAT_8_BIT)
	{

		unsigned char *desttemp=new unsigned char [w*h*3];
		memset(desttemp,0,w*h*3);

		unsigned char *destptr=desttemp;
		unsigned char *srcptr=sourcedata;

		unsigned char col;

		for (int k=0;k<w*h;k++)
		{			
			col=*srcptr++;
			*destptr++=col;		
			*destptr++=col;	
			*destptr++=col;		
		}
		
		sourcedata=desttemp;

		sourceformat=FORMAT_24_BIT;
	}

	TargaHeader_t header;

	memset(&header, 0, sizeof(header));
	header.image_type = 2;
	header.width = w;
	header.height = h;
	header.pixel_size = sourceformat;
  	
	unsigned char *data = new unsigned char[w*h*(sourceformat>>3)];
	unsigned char *dest = data;
	unsigned char *source = sourcedata;

	//memcpy(dest,source,w*h*(sourceformat>>3));
	
	for (int ax = 0; ax < h; ax++)
	{
		for (int by = 0; by < w; by++)
		{
			unsigned char r, g, b, a;
			r = *source; source++;
			g = *source; source++;
			b = *source; source++;
			if (sourceformat==FORMAT_32_BIT) 
			{
				a = *source; source++;
			}				
			*dest = b; dest++;
			*dest = g; dest++;
			*dest = r; dest++;
			if (sourceformat==FORMAT_32_BIT) 
			{
				*dest = a; dest++;
			}
		}
	}
	

	FILE *f = fxopen(filename,"wb");
	if (!f)
	{		
		//("Cannot save %s\n",filename);
		delete [] data;
		return (false);
	}

	if (!fwrite(&header, sizeof(header),1,f))
	{		
		//CLog::LogToFile("Cannot save %s\n",filename);
		delete [] data;
		fclose(f);
		return (false);
	}

	if (!fwrite(data, w*h*(sourceformat>>3),1,f))
	{		
		//CLog::LogToFile("Cannot save %s\n",filename);
		delete [] data;
		fclose(f);
		return (false);
	}

	fclose(f);	

	delete [] data;
	if (sourcedata!=oldsourcedata)
		delete [] sourcedata;

	return (true);	  
}

//================================================================

void CRenderer::EF_ReleaseInputShaderResource(SInputShaderResources *pRes)
{
  pRes->Cleanup();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

//#include "../Common/Character/CryModel.h"












void CRenderer::ForceSwapBuffers()
{
	m_pRT->RC_ForceSwapBuffers();
	ForceFlushRTCommands();
}

void CRenderer::InitSystemResources(int nFlags)
{
	if (!m_bSystemResourcesInit || m_bDeviceLost == 2)
	{











		iLog->Log("*** Init system render resources ***");

		bool bPrecache = CTexture::s_bPrecachePhase;
		CTexture::s_bPrecachePhase = false;

		ForceFlushRTCommands();
		m_cEF.mfPreloadBinaryShaders();
		m_cEF.mfLoadBasicSystemShaders();
		m_cEF.mfLoadDefaultSystemShaders();






		CTexture::LoadScaleformSystemTextures();
		CTexture::LoadDefaultSystemTextures();
		m_pRT->RC_CreateRenderResources();
		m_pRT->RC_PrecacheDefaultShaders();
		CTexture::CreateSystemTargets();
		ForceFlushRTCommands();

    /*m_pRT->RC_BeginFrame();
		SetState(GS_BLSRC_SRCALPHA|GS_BLDST_ONEMINUSSRCALPHA|GS_NODEPTHTEST);
    SetCullMode(R_CULL_NONE); 
		Draw2dImage(0, 0, 800.f, 600.f, -1,
			0.0f,0.0f,1.0f,1.0f, 0.f, 0.f,0.f,0.f,1.f,0.f);
    m_pRT->RC_EndFrame(false);
    ForceFlushRTCommands();*/
 
		CTexture::s_bPrecachePhase = bPrecache;

		if (m_bDeviceLost == 2)
			m_bDeviceLost = 0;
		m_bSystemResourcesInit = 1;






	}
}

void CRenderer::FreeResources(int nFlags)
{
  iLog->Log("*** Start clearing render resources ***");

  if (m_bEditor)
    return;

	CTimeValue tBegin = gEnv->pTimer->GetAsyncTime();






	StopLoadtimeFlashPlayback();

#if !defined(_RELEASE)
	ClearDrawCallsInfo();
#endif
  CHWShader::mfFlushPendedShadersWait(-1);

	EF_ReleaseDeferredData();

	if (nFlags & FRR_FLUSH_TEXTURESTREAMING)
	{
    m_pRT->RC_FlushTextureStreaming();
	}

	if (nFlags & FRR_DELETED_MESHES)
	{
		for (size_t i=0; i<MAX_RELEASED_MESH_FRAMES; ++i)
			m_pRT->RC_ForceMeshGC(true, true);
	}

  if (nFlags & FRR_SHADERS)
    gRenDev->m_cEF.ShutDown();

	if (nFlags & FRR_RP_BUFFERS)
	{
    ForceFlushRTCommands();

		for (int i = 0; i < RT_COMMAND_BUF_COUNT; ++ i)
		{
			for (int j = 0; j < MAX_REND_RECURSION_LEVELS; ++ j)
			{
				TArray<CREClientPoly *>& storage = CREClientPoly::m_PolysStorage[i][j];
				storage.SetUse(storage.Capacity());
				for (size_t poly = 0, polyCount = storage.Capacity(); poly != polyCount; ++ poly)
				{
					if (storage[poly])
						storage[poly]->Release(false);
				}
				storage.Free();

				m_RP.m_SMFrustums[i][j].Free();
				m_RP.m_DLights[i][j].Free();
				m_RP.m_DeferrredDecals[i][j].Free();
			}

			m_RP.m_fogVolumeContibutions[i].Free();
		}

		for (int i = 0; i < sizeof(m_RP.m_RIs) / sizeof(m_RP.m_RIs[0]); ++ i)
			m_RP.m_RIs[i].Free();

		stl::for_each_array(m_RP.m_SysVertexPool, stl::container_freer());
		stl::for_each_array(m_RP.m_SysIndexPool, stl::container_freer());
		stl::free_container(m_RP.m_Polygons);
		stl::for_each_array(m_RP.m_TerrainAONodes, stl::container_freer());
		SRendItem::ResetRendItems();

		for(ShadowFrustumListsCache::iterator it = m_FrustumsCache.begin();
			it != m_FrustumsCache.end(); ++it)
			SAFE_DELETE(it->second);
	}

  if (nFlags & (FRR_SYSTEM | FRR_OBJECTS))
  {
		uint32 i, j;

		for(i = 0; i < sizeof(m_RP.m_FreeObjects) / sizeof(m_RP.m_FreeObjects[0]); ++ i)
		{
			CRenderObject::FlushFreeObjects(i);
			m_RP.m_FreeObjects[i].clear();
		}
    for (i=SRenderPipeline::sPermObjCount; i<m_RP.m_Objects.size(); i++)
    {
      CRenderObject *obj = m_RP.m_Objects[i];
      if (!obj || !(obj->m_ObjFlags & FOB_REMOVED))
        continue;
			delete obj;
			m_RP.m_Objects[i] = NULL;
    }
		m_RP.m_AvailableObjects.Free();
		ForceFlushRTCommands();
    for (j=0; j<RT_COMMAND_BUF_COUNT; j++)
    {
			m_RP.m_TempObjects[j].resize(m_RP.m_TempObjects[j].capacity());
			for (i=m_RP.m_nNumObjectsInPool; i<m_RP.m_TempObjects[j].size(); i++)
      {
        delete m_RP.m_TempObjects[j][i];
				m_RP.m_TempObjects[j][i]=NULL;
      }
      m_RP.m_TempObjects[j].clear();
			stl::free_container( CRenderObject::m_sObjData[j] );
    }
	}

	if (nFlags & FRR_TEXTURES)
	{
		ForceFlushRTCommands();
		CTexture::ShutDown();
	}

  if (nFlags & FRR_SYSTEM)
  {
    for (uint32 i=SRenderPipeline::sPermObjCount; i<m_RP.m_Objects.size(); i++)
		{
			CRenderObject *obj = m_RP.m_Objects[i];
			if (!obj)
				continue;
			delete obj;
			m_RP.m_Objects[i] = NULL;
    }
    m_RP.m_Objects.clear();
    for (uint32 j=0; j<RT_COMMAND_BUF_COUNT; j++)
    {
			m_RP.m_TempObjects[j].clear();
		}
    SAFE_DELETE_ARRAY(m_RP.m_ObjectsPool);
    FX_PipelineShutdown();
  }
  if (nFlags == FRR_ALL)
  {
    ForceFlushRTCommands();
    CRendElementBase::ShutDown();
  }
	else
  if (nFlags & FRR_RENDERELEMENTS )
	{
		CRendElement::Cleanup();
		EF_CleanupParticles();
	}

	if (nFlags & FRR_POST_EFFECTS)
	{
    if (m_pPostProcessMgr)
		  m_pPostProcessMgr->ReleaseResources();
	}

  if (nFlags & FRR_SYSTEM_RESOURCES)
  {
		// Free sprite vertices (indices are packed into the same buffer so no need to free them explicitly);
		CryModuleMemalignFree(m_pSpriteVerts);
		m_pSpriteVerts = NULL;
		m_pSpriteInds = NULL;

		m_p3DEngineCommon.m_RainOccluders.Release(true);

    m_pRT->RC_UnbindResources();
    ForceFlushRTCommands();

		if (m_pRT->IsRenderThread())
		{
			CRenderMesh::Tick();
		}

		ForceFlushRTCommands();

		m_cEF.mfReleaseSystemShaders();
    ForceFlushRTCommands();

		if (m_pPostProcessMgr)
    m_pRT->RC_ReleaseRenderResources();
    ForceFlushRTCommands();

		if (m_pPostProcessMgr)
			m_pPostProcessMgr->ReleaseResources();

		ForceFlushRTCommands();
		CTexture::FlushAllStreamingTasks(true);

		ForceFlushRTCommands();

		CTexture::ReleaseSystemTextures();

#if defined (DIRECT3D10)
		m_pRT->RC_UnbindTMUs();
		ForceFlushRTCommands();
		CTexture::ResetTMUs();
#endif

		CRendElement::Cleanup();
    ForceFlushRTCommands();

#if !defined (_RELEASE)
		ClearTexturePoolAllocationList(m_RP.m_nFillThreadID);
		ClearTexturePoolAllocationList(m_RP.m_nProcessThreadID);
#endif









    PrintResourcesLeaks();

    if (!m_bDeviceLost)
      m_bDeviceLost = 2;
		m_bSystemResourcesInit = 0;

  }

  if ((nFlags & FRR_RESTORE) && !(nFlags & FRR_SYSTEM))
    m_cEF.mfInit();

	CTimeValue tDeltaTime = gEnv->pTimer->GetAsyncTime() - tBegin;
	iLog->Log("*** Clearing render resources took %.1f msec ***", tDeltaTime.GetMilliSeconds());
}

EScreenAspectRatio CRenderer::GetScreenAspect(int nWidth, int nHeight)
{
  EScreenAspectRatio eSA = eAspect_Unknown;

  float fNeed16_9 = 16.0f / 9.0f;
  float fNeed16_10 = 16.0f / 10.0f;
  float fNeed4_3 = 4.0f / 3.0f;

  float fCur = (float)nWidth / (float)nHeight;
  if (fabs(fCur-fNeed16_9) < 0.1f)
    eSA = eAspect_16_9;

  if (fabs(fCur-fNeed4_3) < 0.1f)
    eSA = eAspect_4_3;

  if (fabs(fCur-fNeed16_10) < 0.1f)
    eSA = eAspect_16_10;

  return eSA;
}

bool CRenderer::WriteTGA(byte *dat, int wdt, int hgt, const char *name, int src_bits_per_pixel, int dest_bits_per_pixel)
{
	return ::WriteTGA((byte*)dat, wdt, hgt, name, src_bits_per_pixel,dest_bits_per_pixel);
}

const char *sourceFile;
unsigned int sourceLine;


bool CRenderer::WriteDDS(byte *dat, int wdt, int hgt, int Size, const char *nam, ETEX_Format eFDst, int NumMips)
{
	bool bRet=true;

  byte *data = NULL;
  if (Size == 3)
  {
    data = new byte[wdt*hgt*4];
    for (int i=0;  i<wdt*hgt; i++)
    {
      data[i*4+0] = dat[i*3+0];
      data[i*4+1] = dat[i*3+1];
      data[i*4+2] = dat[i*3+2];
      data[i*4+3] = 255;
    }
    dat = data;
  }
  char name[256];
  fpStripExtension(nam, name);
  strcat(name, ".dds");

  bool bMips = false;
  if (NumMips != 1)
    bMips = true;
  int nDxtSize;
  byte *dst = CTexture::Convert(dat, wdt, hgt, NumMips, eTF_A8R8G8B8, eFDst, NumMips, nDxtSize, true);
  if (dst)
  {
    ::WriteDDS(dst, wdt, hgt, 1, name, eFDst, NumMips, eTT_2D);
    delete [] dst;
  }
  if (data)
    delete [] data;

	return bRet;
}

void CRenderer::EF_SetShaderMissCallback(ShaderCacheMissCallback callback)
{
	m_cEF.m_ShaderCacheMissCallback = callback;
}

const char* CRenderer::EF_GetShaderMissLogPath()
{
	return m_cEF.m_ShaderCacheMissPath.c_str();
}

string *CRenderer::EF_GetShaderNames(int& nNumShaders)
{
  nNumShaders = m_cEF.m_ShaderNames.size();
  return &m_cEF.m_ShaderNames[0];
}

IShader *CRenderer::EF_LoadShader (const char *name, int flags, uint64 nMaskGen)
{
#ifdef NULL_RENDERER
  return m_cEF.m_DefaultShader;
#else
  return m_cEF.mfForName(name, flags, NULL, nMaskGen);
#endif
}

void CRenderer::EF_SetShaderQuality(EShaderType eST, EShaderQuality eSQ)
{
	m_pRT->RC_SetShaderQuality(eST, eSQ);
}

uint64 CRenderer::EF_GetRemapedShaderMaskGen( const char *name, uint64 nMaskGen, bool bFixup )
{
	return m_cEF.mfGetRemapedShaderMaskGen( name, nMaskGen, bFixup);
}

uint64 CRenderer::EF_GetShaderGlobalMaskGenFromString( const char *szShaderName, const char *szShaderGen, uint64 nMaskGen )
{
  if( !m_cEF.mfUsesGlobalFlags( szShaderName ) )
    return nMaskGen;

  return m_cEF.mfGetShaderGlobalMaskGenFromString( szShaderGen );
}

// inverse of EF_GetShaderMaskGenFromString
const char *CRenderer::EF_GetStringFromShaderGlobalMaskGen( const char *szShaderName, uint64 nMaskGen ) 
{
  if( !m_cEF.mfUsesGlobalFlags( szShaderName ) )
    return "\0";

  return m_cEF.mfGetShaderBitNamesFromGlobalMaskGen( nMaskGen );
}

SShaderItem CRenderer::EF_LoadShaderItem (const char *szName, bool bShare, int flags, SInputShaderResources *Res, uint64 nMaskGen)
{
	LOADING_TIME_PROFILE_SECTION(GetISystem());

#ifdef NULL_RENDERER
	return m_cEF.m_DefaultShaderItem;
#else
  return m_cEF.mfShaderItemForName(szName, bShare, flags, Res, nMaskGen);
#endif
}

//////////////////////////////////////////////////////////////////////////
bool CRenderer::EF_ReloadFile(const char *szFileName)
{
	string unixFileName = PathUtil::ToUnixPath(szFileName);

	const string gameFolder = PathUtil::AddSlash(PathUtil::GetGameFolder());
	const size_t foundGameFolderPos = unixFileName.find(gameFolder);

	if (foundGameFolderPos != string::npos)
		unixFileName.replace(0, foundGameFolderPos+gameFolder.length(), "");

	const string extension = PathUtil::GetExt(unixFileName);
	const bool bIsDDS = (extension == "dds");
	const bool bIsTIF = (extension == "tif");
	bool bSwitchedToTIF = false;

#if defined(CRY_ENABLE_RC_HELPER)
	if (bIsTIF || bIsDDS)
	{
		// Usually reloading a dds will automatically trigger the resource compiler if necessary to
		// compile the .tif into a .dds. However, this does not happen if texture streaming is
		// enabled, so we explicitly run the resource compiler here.
		if (bIsDDS)
		{
			unixFileName = PathUtil::ReplaceExtension(unixFileName, "tif");
			bSwitchedToTIF = true;
		}
	
		char buffer[512];
		CResourceCompilerHelper().ProcessIfNeeded(unixFileName.c_str(), buffer, sizeof(buffer));
	}
#endif //defined(CRY_ENABLE_RC_HELPER)

	if (bSwitchedToTIF)
		unixFileName = PathUtil::ReplaceExtension(unixFileName, "dds");

  if (extension == "cgf")
  {
	  IStatObj * pStatObjectToReload = gEnv->p3DEngine->FindStatObjectByFilename(unixFileName.c_str());
	  if ( pStatObjectToReload )
	  {
		  pStatObjectToReload->Refresh(FRO_GEOMETRY|FRO_SHADERS|FRO_TEXTURES);
			return true;
	  }
		return false;
  }
  else if (extension == "cfx" || (!CV_r_shadersignoreincludeschanging && extension == "cfi"))
  {
	  gRenDev->m_cEF.m_Bin.InvalidateCache();
	  // This is a temporary fix so that shaders would reload during hot update.
	  return gRenDev->m_cEF.mfReloadAllShaders(FRO_SHADERS, 0);
  }
  else if (bIsTIF || bIsDDS || extension == "tga" || extension == "pcx" || extension == "jpg" || extension == "gif" || extension == "bmp")
  {
	  return CTexture::ReloadFile(unixFileName.c_str());
  }
  return false;
}

void CRenderer::EF_ReloadShaderFiles (int nCategory)
{
  //gRenDev->m_cEF.mfLoadFromFiles(nCategory);
}

void CRenderer::EF_ReloadTextures ()
{
  CTexture::ReloadTextures();
}

bool CRenderer::EF_ScanEnvironmentCM (const char *name, int size, Vec3& Pos)
{
  return CTexture::ScanEnvironmentCM(name, size, Pos);
}

bool CRenderer::EF_RenderEnvironmentCubeHDR (int size, Vec3& Pos, TArray<unsigned short>& vecData)
{
	return CTexture::RenderEnvironmentCMHDR(size, Pos, vecData);
}

int CRenderer::EF_LoadLightmap (const char *name)
{
  CTexture *tp = (CTexture *)EF_LoadTexture(name, FT_DONT_STREAM | FT_STATE_CLAMP | FT_NOMIPS);
  if (tp->IsTextureLoaded())
    return tp->GetID();
  else
    return -1;
}

ITexture *CRenderer::EF_GetTextureByID(int Id)
{
  if (Id > 0)
  {
    CTexture *tp = CTexture::GetByID(Id);
    if (tp)
      return tp;
  }
  return NULL;
}

ITexture *CRenderer::EF_GetTextureByName(const char *name, uint32 flags)
{
  if (name)
  {
    CTexture *tp = CTexture::GetByName(name, flags);
    
		if (tp)
      return tp;
  }
  return NULL;
}

ITexture *CRenderer::EF_LoadTexture(const char* nameTex, const uint32 flags)
{
#if defined (NULL_RENDERER)
  if (CTexture::s_ptexNoTexture)
    return CTexture::s_ptexNoTexture;
  else
#endif
  {
		const char *ext = fpGetExtension(nameTex);
		if(ext!=0 && stricmp(ext,".tif")==0)		// for TIF files, register by the dds file name (to not load it twice)
		{
			char name[256];
			fpStripExtension(nameTex, name);
			strcat(name, ".dds");

	    return CTexture::ForName(name, flags, eTF_Unknown);
		}
		else
      return CTexture::ForName(nameTex, flags, eTF_Unknown);
  }
}

IDynTextureSource *CRenderer::EF_LoadDynTexture(const char* dynsourceName, bool sharedRT)
{
#if defined (NULL_RENDERER)
	return NULL;
#endif
	if (sharedRT)
		return new CFlashTextureSourceSharedRT(dynsourceName);

	return new CFlashTextureSource(dynsourceName);
}


bool SShaderItem::Update()
{
  if (!(m_pShader->GetFlags() & EF_LOADED))
    return false;
  if ((uint32)m_nTechnique > 1000 && m_nTechnique != -1) // HACK HACK HACK
  {
    CCryNameTSCRC Name(m_nTechnique);
    if (!gRenDev->m_cEF.mfUpdateTechnik(*this, Name))
      return false;
  }
  m_nPreprocessFlags = 0;
  PostLoad();

  return true;
}

TArray<SRenderObjData> CRenderObject::m_sObjData[RT_COMMAND_BUF_COUNT];
ILINE TArray<SRenderObjData>& ObjData(int nThreadIndex)
{
	return CRenderObject::m_sObjData[nThreadIndex];
}

void CRenderer::EF_StartEf ()
{
	FUNCTION_PROFILER_FAST( GetISystem(),PROFILE_RENDERER,g_bProfilerEnabled );
  int i, j;
	ASSERT_IS_MAIN_THREAD(m_pRT)
  int nThreadID = m_RP.m_nFillThreadID;  
  int nR = SRendItem::m_RecurseLevel[nThreadID];
  if (nR >= MAX_REND_RECURSION_LEVELS)
		return;

  if (nR <= 0)
  {
    SRendItem::m_RecurseLevel[nThreadID] = 0;
    for (j=0; j<MAX_LIST_ORDER; j++)
    {
			for (i=0; i<EFSLIST_NUM; i++)
			{
				SRendItem::RendItems(nThreadID,j,i).SetUse(0);
				SRendItem::m_AppStartRI[nR][j][i] = 0;
			}
    }

    m_RP.m_TempObjects[nThreadID].SetUse(1);
    ObjData(nThreadID).SetUse(0);

    //SG frustums
    //SRendItem::m_ShadowGenRecurLevel[nThreadID] = 0;
    for (i=0; i<MAX_SHADOWMAP_FRUSTUMS; i++)
    {
      SRendItem::m_ShadowsStartRI[nThreadID][i] = 0;
      SRendItem::m_ShadowsEndRI[nThreadID][i] = 0;
    }

    for (i=0; i<(MAX_REND_LIGHTS+MAX_DEFERRED_LIGHTS); i++)
    {
      SRendItem::m_StartFrust[nThreadID][i] = 0;
      SRendItem::m_EndFrust[nThreadID][i] = 0;
    }

		// Clear all cached lists of shadow frustums
		for(ShadowFrustumListsCache::iterator it = m_FrustumsCache.begin(); it != m_FrustumsCache.end(); ++it)
		{
			if (it->second)
				it->second->Clear();
		}

    EF_RemovePolysFromScene();
		m_RP.m_fogVolumeContibutions[nThreadID].Clear();
  }

  for (j=0; j<MAX_LIST_ORDER; j++)
  {
    for (i=0; i<EFSLIST_NUM; i++)
    {
      SRendItem::m_AppStartRI[nR][j][i] = SRendItem::RendItems(nThreadID,j,i).Num();
      SRendItem::m_BatchFlags[nR][j][i] = 0;
    }
  }
  m_RP.m_RejectedObjects[nThreadID].SetUse(0);
  //EF_PushObjectsList(nID);

  m_RP.m_DeferrredDecals[nThreadID][nR].SetUse(0);
	m_RP.m_isDeferrredNormalDecals[nThreadID][nR] = false;


	CPostEffectsMgr* pPostEffectMgr = PostEffectMgr();

	if(pPostEffectMgr)
	{
		pPostEffectMgr->OnBeginFrame();
	}

  SRendItem::m_RecurseLevel[nThreadID]++;
	SRendItem::m_RenderView[nThreadID][nR] = 0;

  EF_ClearLightsList();
}


uint32 CRenderer::EF_BatchFlags(SShaderItem& SH, CRenderObject *pObj, int nThreadID, CRendElementBase *re)
{
	uint32 nFlags = SH.m_nPreprocessFlags & FB_MASK;
  if (SH.m_nPreprocessFlags & FSPR_GENSPRITES)
    nFlags |= FB_PREPROCESS;
	SShaderTechnique *const __restrict pTech = SH.GetTechnique();
	SRenderShaderResources *const __restrict pR = (SRenderShaderResources *)SH.m_pShaderResources;
	CShader *const __restrict pS = (CShader *)SH.m_pShader;

	const int RecurseLevel = SRendItem::m_RecurseLevel[nThreadID];
	float  fAlpha = pObj->m_fAlpha;
	uint32 uTransparent = (bool)(fAlpha < 1.0f);
	const uint32 ObjFlags = pObj->m_ObjFlags;

	if (RecurseLevel == 1 && pTech)
	{
		CryPrefetch(pTech->m_nTechnique);
		CryPrefetch(pR);

		//if (pObj->m_fAlpha < 1.0f) nFlags |= FB_TRANSPARENT;
		nFlags |= FB_TRANSPARENT * uTransparent;

		if (!( (nFlags & FB_Z) && (!(ObjFlags & FOB_NO_Z_PASS) || (pS->m_Flags2 & EF2_FORCE_ZPASS)) ) )
			nFlags &= ~FB_Z;

#if !defined(XENON) && !defined(PS3) && !defined(CAFE)
		if (pTech->m_nTechnique[TTYPE_DEBUG] > 0 && 0 != (ObjFlags & FOB_SELECTED))
			nFlags |= FB_DEBUG;
#endif

		const uint32 nMaterialLayers = pObj->m_nMaterialLayers;
		const uint32 DecalFlags = pS->m_Flags & EF_DECAL;

		//if (bShadowGen) nFlags &= ~FB_PREPROCESS;
		uint32 uMask = m_RP.m_TI[nThreadID].m_PersFlags & RBPF_SHADOWGEN;
		uTransparent = nz2mask(uMask);

		nFlags &= ~(FB_PREPROCESS & uTransparent);

		if ( (nMaterialLayers & ~uTransparent) && CV_r_usemateriallayers)
		{
			const uint32 nResourcesNoDrawFlags = pR->GetMtlLayerNoDrawFlags();

			// if ((nMaterialLayers & MTL_LAYER_BLEND_DYNAMICFROZEN) && !(nResourcesNoDrawFlags & MTL_LAYER_FROZEN))
			uMask = mask_nz_zr(nMaterialLayers & MTL_LAYER_BLEND_DYNAMICFROZEN, nResourcesNoDrawFlags & MTL_LAYER_FROZEN);

			nFlags |= FB_MULTILAYERS & uMask;


			//if ((nMaterialLayers & MTL_LAYER_BLEND_CLOAK) && !(nResourcesNoDrawFlags&MTL_LAYER_CLOAK))
			uMask = mask_nz_zr(nMaterialLayers & MTL_LAYER_BLEND_CLOAK, nResourcesNoDrawFlags & MTL_LAYER_CLOAK);

			//prevent general pass when fully cloaked			
			nFlags &= ~(uMask & (FB_TRANSPARENT | (((nMaterialLayers & MTL_LAYER_BLEND_CLOAK) == MTL_LAYER_BLEND_CLOAK) ? FB_GENERAL : 0)));
			nFlags |=   uMask & (FB_TRANSPARENT | FB_MULTILAYERS);
					}

		//if ( ((ObjFlags & (FOB_DECAL|FOB_VEGETATION)) | DecalFlags) == 0 ) // put the mask below
		{
			if (pTech->m_nTechnique[TTYPE_MOTIONBLURPASS] > 0 && (ObjFlags & FOB_HAS_PREVMATRIX) && CRenderer::s_AllowMotionBlur)
			{
				uMask = mask_zr_zr(ObjFlags & (FOB_DECAL|FOB_VEGETATION), DecalFlags);
				nFlags |= FB_MOTIONBLUR & uMask;
			}
		}

    SRenderObjData *pOD = pObj->GetObjData(nThreadID);
		if (pTech->m_nTechnique[TTYPE_CUSTOMRENDERPASS] > 0 && (pOD))
		{			
			const uint32 nVisionParams = (pOD && pOD->m_nVisionParams);//pObj->m_nVisionParams;
			if (m_nThermalVisionMode && (pR->HeatAmount_unnormalized() || nVisionParams))
				nFlags |= FB_CUSTOM_RENDER;

			const uint32 customvisions = CRenderer::CV_r_customvisions;
			const uint32 nHUDSilhouettesParams = (pOD && pOD->m_nHUDSilhouetteParams);
			if (customvisions && !(ObjFlags & FOB_VEGETATION) && nHUDSilhouettesParams)
					nFlags |= FB_CUSTOM_RENDER;
		}

		if(pOD && (pOD->m_nCustomFlags & COB_POST_3D_RENDER))
		{
			nFlags |= FB_POST_3D_RENDER;
		}

		if (nFlags & FB_LAYER_EFFECT)
		{
			if (((ObjFlags & FOB_VEGETATION) || !pOD || !pOD->m_pLayerEffectParams) && !CV_r_DebugLayerEffect)
				nFlags &= ~FB_LAYER_EFFECT;
		}
	}
	else
		if( RecurseLevel > 1 && pTech && m_RP.m_TI[nThreadID].m_PersFlags & RBPF_MIRRORCAMERA)
		{
			nFlags &=(FB_TRANSPARENT | FB_CAUSTICS | FB_GENERAL);
			nFlags |= FB_TRANSPARENT * uTransparent;                                    // if (pObj->m_fAlpha < 1.0f)                   nFlags |= FB_TRANSPARENT;
			nFlags |= FB_CAUSTICS * (uint32)(pTech->m_nTechnique[TTYPE_CAUSTICS] > 0);  // if (pTech->m_nTechnique[TTYPE_CAUSTICS] > 0) nFlags |= FB_CAUSTICS; 
		}

		{
			//if ( (objFlags & FOB_ONLY_Z_PASS) || CV_r_ZPassOnly) && !(nFlags & (FB_TRANSPARENT | FB_SCATTER))) - put it to the mask
			const uint32 mask =  mask_nz_zr((uint32)CV_r_ZPassOnly, nFlags & (FB_TRANSPARENT | FB_SCATTER));

			nFlags = iselmask(mask, FB_Z, nFlags);
		}

		int nShaderFlags = (SH.m_pShader ? SH.m_pShader->GetFlags() : 0);
		if((CRenderer::CV_r_RefractionPartialResolves && nShaderFlags & EF_REFRACTIVE) ||	(nShaderFlags & EF_FORCEREFRACTIONUPDATE))
			pObj->m_ObjFlags |= FOB_REQUIRES_RESOLVE;

		return nFlags;
}

#ifdef _DEBUG
static float sMatIdent[12] = 
{
  1,0,0,0,
  0,1,0,0,
  0,0,1,0
};
#endif


void CRenderer::EF_AddEf_NotVirtual (CRendElementBase *re, SShaderItem& SH, CRenderObject *obj, int nList, int nAW)
{
  assert(nList>0 && nList<EFSLIST_NUM);  
  
  if (!re || !SH.m_pShader)
    return;

  CShader *const __restrict pSH = (CShader *)SH.m_pShader;
	const uint32 nShaderFlags = pSH->m_Flags;
  if (nShaderFlags & EF_NODRAW)
    return;

	const uint32 nMaterialLayers = obj->m_nMaterialLayers;

	SRenderShaderResources *const __restrict pShaderResources = (SRenderShaderResources *)SH.m_pShaderResources;
  if (SH.m_nPreprocessFlags == -1 || (nShaderFlags & EF_RELOADED))
  {
    pSH->m_Flags &= ~EF_RELOADED;
    if (!SH.Update())
      return;
  }

	const uint32 nCloakMask = mask_nz_zr(nMaterialLayers & MTL_LAYER_BLEND_CLOAK, pShaderResources ? pShaderResources->GetMtlLayerNoDrawFlags() & MTL_LAYER_CLOAK : 0);

  ASSERT_IS_MAIN_THREAD(m_pRT)

  int nThreadID = m_RP.m_nFillThreadID;
  SThreadInfo& RESTRICT_REFERENCE rTI = m_RP.m_TI[nThreadID];

	if (rTI.m_PersFlags & RBPF_SHADOWGEN) 
	{
		if (pSH->m_HWTechniques.Num() && pSH->m_HWTechniques[0]->m_nTechnique[TTYPE_SHADOWGEN] >= 0)
      SRendItem::mfAdd(nThreadID, re, obj, SH, EFSLIST_SHADOW_GEN, SG_SORT_GROUP, FB_GENERAL);
	  return;
	}
  // Discard 0 alpha blended geometry - this should be discarded earlier on 3dengine side preferably
  if (fzero(obj->m_fAlpha)) 
		return;
	if (pShaderResources && fzero(&pShaderResources->::SRenderShaderResources::GetOpacity())) 
		return;

#ifdef _DEBUG
  if (memcmp(sMatIdent, obj->m_II.m_Matrix.GetData(), 3*4*4))
  {
    if (!(obj->m_ObjFlags & FOB_TRANS_MASK))
    {
      assert(0);
    }
  }
#endif

  if (!(obj->m_ObjFlags & FOB_UPDATED_RTMASK))
  {
		EF_AddEf_HandleOldRTMask(obj);
  }
  
  uint32 nBatchFlags = EF_BatchFlags(SH, obj, nThreadID, re);

	const uint32 nRenderlistsFlags = (FB_PREPROCESS|FB_MULTILAYERS|FB_TRANSPARENT);
	if (nBatchFlags & nRenderlistsFlags)
	{
		if (nBatchFlags & FB_PREPROCESS) 
		{
			EShaderType eSHType = pSH->GetShaderType();

			// Prevent water usage on non-water specific meshes (it causes reflections updates). Todo: this should be checked in editor side and not allow such usage
			if (eSHType != eST_Water || (eSHType == eST_Water && nList == EFSLIST_WATER))
				SRendItem::mfAdd(nThreadID, re, obj, SH, EFSLIST_PREPROCESS, 0, nBatchFlags);
		}

		{
			// branchless version of:
			//if      (pSH->m_Flags & FB_REFRACTIVE || nCloakMask)                nList = EFSLIST_TRANSP, nBatchFlags &= ~FB_Z;
			//else if((nBatchFlags & FB_TRANSPARENT) && nList == EFSLIST_GENERAL) nList = EFSLIST_TRANSP;

      // Refractive objects go into same list as transparent objects - partial resolves support
      // arbitrary ordering between transparent and refractive correctly.

			uint32 mx1 = (nShaderFlags & EF_REFRACTIVE) | nCloakMask;
			uint32 mx2 = mask_nz_zr(nBatchFlags & FB_TRANSPARENT, (nList ^ EFSLIST_GENERAL) | mx1);

			nBatchFlags &= iselmask(mx1 = nz2mask(mx1), ~FB_Z, nBatchFlags);
			nList        = iselmask(mx1 | mx2, (mx1 & EFSLIST_TRANSP) | (mx2 & EFSLIST_TRANSP), nList);

		}
	}
  if ((nBatchFlags & FB_TRANSPARENT) || (SRendItem::m_RecurseLevel[nThreadID] > 1) /* account for recursive scene traversal done in forward fashion*/) 
  {
    SRenderObjData *pOD = EF_GetObjData(obj, true);
    if (pOD && pOD->m_FogVolumeContribIdx[nThreadID] == (uint16) -1)
    {
      I3DEngine *pEng = gEnv->p3DEngine;
      ColorF newContrib;
      pEng->TraceFogVolumes(obj->GetTranslation(), newContrib);

      pOD->m_FogVolumeContribIdx[nThreadID] = PushFogVolumeContribution(newContrib);
    }
  } 

	//if (nList != EFSLIST_GENERAL && nList != EFSLIST_TERRAINLAYER) nBatchFlags &= ~FB_Z;
	nBatchFlags &= ~(FB_Z & mask_nz_nz(nList ^ EFSLIST_GENERAL, nList ^ EFSLIST_TERRAINLAYER));

	nList = (nBatchFlags& FB_SKIN)? EFSLIST_SKIN : nList; 

  const uint32 nShaderFlags2 = pSH->m_Flags2;
	const uint32 ObjDecalFlag = obj->m_ObjFlags & FOB_DECAL;

  // make sure decals go into proper render list 
  // also, set additional shadow flag (i.e. reuse the shadow mask generated for underlying geometry)
  // TODO: specify correct render list and additional flags directly in the engine once non-material decal rendering support is removed! 
	if ((ObjDecalFlag || (nShaderFlags & EF_DECAL)))
	{         
		//if ((rTI.m_PersFlags & RBPF_SHADOWGEN) && (!m_RP.m_pCurShadowFrustumFillThread || !m_RP.m_pCurShadowFrustumFillThread->bReflectiveShadowMap))
		//	return;

		// BK: Drop decals that are refractive (and cloaked!). They look bad if forced into refractive pass,
		// and break if they're in the decal pass
		//if(nList == EFSLIST_REFRACTPASS || (obj->m_nMaterialLayers & MTL_LAYER_BLEND_CLOAK) ) //== MTL_LAYER_BLEND_CLOAK
		//	return;
		
		//SShaderTechnique *pTech = SH.GetTechnique();    
		//if (pTech && pTech->m_nTechnique[TTYPE_Z] > 0 && ((nShaderFlags2 & EF2_FORCE_ZPASS) || CV_r_deferredshading)) // deferred shading always enabled
		{
			// temporary hack: if no normal map use base normal from NormalsTarget          
			// todo: make this instead by decal type
			if ((nShaderFlags2 & EF2_FORCE_ZPASS) || pShaderResources && pShaderResources->GetTexture(EFTT_BUMP))
				nBatchFlags |= FB_Z; 
		}

		nList = EFSLIST_DECAL;
		obj->m_ObjFlags |= FOB_INSHADOW;

		if (ObjDecalFlag == 0 && pShaderResources)
			obj->m_nSort = pShaderResources->m_SortPrio;
	}

	// Enable tessellation for water geometry
	obj->m_ObjFlags |= (pSH->m_Flags2 & EF2_HW_TESSELLATION && pSH->m_eShaderType == eST_Water)? FOB_ALLOW_TESSELLATION : 0;

  const uint32 nForceFlags = (EF2_FORCE_DRAWLAST|EF2_FORCE_DRAWFIRST|EF2_FORCE_ZPASS|EF2_FORCE_TRANSPASS|EF2_FORCE_GENERALPASS|EF2_FORCE_DRAWAFTERWATER|EF2_FORCE_WATERPASS|EF2_AFTERHDRPOSTPROCESS);

  if (nShaderFlags2 & nForceFlags)
  {
		EF_AddEf_HandleForceFlags(nList, nAW, nBatchFlags, nShaderFlags, nShaderFlags2, obj);
  }

  {
    // Always force cloaked geometry to render after water
		//if (obj->m_nMaterialLayers & MTL_LAYER_BLEND_CLOAK) nAW = 1;   -> branchless
		nAW |= nz2one( obj->m_nMaterialLayers & MTL_LAYER_BLEND_CLOAK);

		// Temporary way to enforce sky and sprites to render last, since:
		// 1. we sort by light mask for zpass atm
		// 2. we don't have any shader information during resources sorting (mfSortResources) which takes higher priority than shader ID
		//if ((nShaderFlags & EF_SKY) || (nShaderFlags2 & EF2_PREPR_GENSPRITES)) obj->m_DynLMMask[nThreadID] = ~0;   -> branchless
		obj->m_DynLMMask[nThreadID] |= nz2mask((nShaderFlags & EF_SKY) | (nShaderFlags2 & EF2_PREPR_GENSPRITES));

		if(nShaderFlags & (EF_REFRACTIVE|EF_FORCEREFRACTIONUPDATE) || nCloakMask)
		{
			SRenderObjData * pOD = EF_GetObjData(obj, CRenderer::CV_r_RefractionPartialResolves == 2); // Creating objData for objs without one

			if(obj->m_pRenderNode && pOD)
			{
				const int32 align16 = (16-1);
				const int32 shift16 = 4;
				if( CRenderer::CV_r_RefractionPartialResolves )
				{
					const AABB aabb  =  ((IRenderNode*)obj->m_pRenderNode)->GetBBox();
		
					int iOut[4];
					GetCamera().CalcScreenBounds(&iOut[0], &aabb, GetWidth(), GetHeight(), 0.75f, 0.75f);
					pOD->m_screenBounds[0] = min(iOut[0] >> shift16, 255);
					pOD->m_screenBounds[1] = min(iOut[1] >> shift16, 255);
					pOD->m_screenBounds[2] = min((iOut[2] + align16) >> shift16, 255);
					pOD->m_screenBounds[3] = min((iOut[3] + align16) >> shift16, 255);
					}
				else if( nShaderFlags & EF_FORCEREFRACTIONUPDATE)
				{
					pOD->m_screenBounds[0] = 0;
					pOD->m_screenBounds[1] = 0;
					pOD->m_screenBounds[2] = min((GetWidth()) >> shift16, 255);
					pOD->m_screenBounds[3] = min((GetHeight()) >> shift16, 255);
				}
			}
		}

		// final step, for post 3d items, remove them from any other list than POST_3D_RENDER
		// (have to do this here as the batch needed to go through the normal nList assign path first)
		nBatchFlags = iselmask(nz2mask(nBatchFlags & FB_POST_3D_RENDER), FB_POST_3D_RENDER, nBatchFlags);
     
		SRendItem::mfAdd(nThreadID, re, obj, SH, nList, nAW, nBatchFlags);
  }
}


void CRenderer::EF_AddEf_HandleForceFlags(int& nList, int& nAW, uint32& nBatchFlags, const uint32 nShaderFlags, const uint32 nShaderFlags2, CRenderObject *obj)
{
	// Force rendering in last place
	// FIXME: If object is permanent this is wrong!
	// branchless
	//if (nShaderFlags2 & EF2_FORCE_DRAWLAST ) obj->m_fSort -= 100000.0f;
	//if (nShaderFlags2 & EF2_FORCE_DRAWFIRST) obj->m_fSort += 100000.0f;

	const int32 sort1 = nz2mask(nShaderFlags2 & EF2_FORCE_DRAWLAST);
	const int32 sort2 = nz2one (nShaderFlags2 & EF2_FORCE_DRAWFIRST);
	CIntToFloat fSort = CIntToFloat(100000*(sort1 + sort2));

	if (nShaderFlags2 & EF2_FORCE_ZPASS && !((nShaderFlags & EF_REFRACTIVE) && (nBatchFlags & FB_MULTILAYERS))) 
		nBatchFlags |= FB_Z;

	{
		// below branchlessw version of:
		//if      (nShaderFlags2 & EF2_FORCE_TRANSPASS  ) nList = EFSLIST_TRANSP;
		//else if (nShaderFlags2 & EF2_FORCE_GENERALPASS) nList = EFSLIST_GENERAL;
		//else if (nShaderFlags2 & EF2_FORCE_WATERPASS  ) nList = EFSLIST_WATER;

		uint32 mb1 = nShaderFlags2 & EF2_FORCE_TRANSPASS;
		uint32 mb2 = nShaderFlags2 & EF2_FORCE_GENERALPASS;
		uint32 mb3 = nShaderFlags2 & EF2_FORCE_WATERPASS;

		mb1 = nz2msb(mb1);
		mb2 = nz2msb(mb2) & ~ mb1;
		mb3 = nz2msb(mb3) & ~(mb1 ^ mb2);

		mb1 = msb2mask(mb1);
		mb2 = msb2mask(mb2);
		mb3 = msb2mask(mb3);

		const uint32 mask = mb1 | mb2 | mb3;
		mb1 &=  EFSLIST_TRANSP;
		mb2 &=  EFSLIST_GENERAL;
		mb3 &=  EFSLIST_WATER;

		nList = iselmask(mask, mb1 | mb2 | mb3, nList);
	}


	// if (nShaderFlags2 & EF2_AFTERHDRPOSTPROCESS) // now it's branchless
	{
		uint32 predicate = nz2mask(nShaderFlags2 & EF2_AFTERHDRPOSTPROCESS);

		const uint32 mask = nz2mask(nShaderFlags2 & EF2_FORCE_DRAWLAST);
		nList = iselmask(predicate, iselmask(mask, EFSLIST_AFTER_POSTPROCESS, EFSLIST_AFTER_HDRPOSTPROCESS), nList);
	}

	if(nShaderFlags2 & EF2_AFTERPOSTPROCESS)
		nList = EFSLIST_AFTER_POSTPROCESS;

	//if (nShaderFlags2 & EF2_FORCE_DRAWAFTERWATER) nAW = 1;   -> branchless
	nAW |= nz2one(nShaderFlags2 & EF2_FORCE_DRAWAFTERWATER);

	obj->m_fSort += fSort.Convert();
}

void CRenderer::EF_AddEf_HandleOldRTMask(CRenderObject *obj)
{
	const uint32 objFlags = obj->m_ObjFlags;
	obj->m_nRTMask = 0;
	if (objFlags & (FOB_VEGETATION | FOB_NEAREST | FOB_DECAL_TEXGEN_2D | FOB_DISSOLVE | FOB_GLOBAL_ILLUMINATION | FOB_SOFT_PARTICLE)) // | FOB_CAMERA_SPACE))
	{
		if (objFlags & FOB_VEGETATION)
			obj->m_nRTMask |= g_HWSR_MaskBit[HWSR_VEGETATION];                

		if (objFlags & FOB_DECAL_TEXGEN_2D)
			obj->m_nRTMask |= g_HWSR_MaskBit[HWSR_DECAL_TEXGEN_2D];

		if (objFlags & FOB_NEAREST)
			obj->m_nRTMask |= g_HWSR_MaskBit[HWSR_NEAREST];

		if (objFlags & FOB_DISSOLVE)
			obj->m_nRTMask |= g_HWSR_MaskBit[HWSR_DISSOLVE];

		if (objFlags & FOB_GLOBAL_ILLUMINATION)
			obj->m_nRTMask |= g_HWSR_MaskBit[HWSR_GLOBAL_ILLUMINATION];

		if (CV_r_usesoftparticles && (objFlags & FOB_SOFT_PARTICLE))
			obj->m_nRTMask |= g_HWSR_MaskBit[HWSR_SOFT_PARTICLE];

#ifdef ALLOW_CAMERA_SPACE
		if (objFlags & FOB_CAMERA_SPACE)
			obj->m_nRTMask |= g_HWSR_MaskBit[HWSR_CAMERA_SPACE];
#endif
	}

	obj->m_ObjFlags |= FOB_UPDATED_RTMASK;
}

void CRenderer::RT_PostLevelLoading()
{
	int nThreadID = m_pRT->GetThreadList();
	m_RP.m_fogVolumeContibutions[nThreadID].reserve( 2048 );

  m_cEF.m_Bin.InvalidateCache();
  CHWShader::mfCleanupCache();
  CResFile::m_nMaxOpenResFiles = 4;
}

void CRenderer::RT_FlashRender(IFlashPlayer_RenderProxy* pPlayer, bool stereo)
{
	m_pRT->RC_FlashRender(pPlayer, stereo);
}

void CRenderer::RT_FlashRenderPlaybackLockless(IFlashPlayer_RenderProxy* pPlayer, int cbIdx, bool stereo, bool finalPlayback)
{
	m_pRT->RC_FlashRenderPlaybackLockless(pPlayer, cbIdx, stereo, finalPlayback);
}

void CRenderer::RT_FlashRemoveTexture(ITexture* pTexture)
{
	pTexture->Release();
}

#if SUPPORT_RENDER_TO_CONTROLLER
void CRenderer::SetRenderToScreenOnController(IRenderToScreenOnController * renderer)
{
	CryLog ("Changing render-to-controller instance from %p to %p", m_renderToScreenOnController, renderer);
	m_pRT->FlushAndWait();
	m_renderToScreenOnController = renderer;
}
#endif

void CRenderer::DrawStringW(IFFont_RenderProxy* pFont, float x, float y, float z, const wchar_t* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) const
{
  m_pRT->RC_DrawStringW(pFont, x, y, z, pStr, asciiMultiLine, ctx);
}

void CRenderer::EF_AddEf (CRendElementBase *re, SShaderItem& pSH, CRenderObject *obj, int nList, int nAW)
{
  EF_AddEf_NotVirtual (re, pSH, obj, nList, nAW);
}

void CRenderer::RT_CreateREPostProcess(CRendElementBase **re)
{
  *re = new CREPostProcess;
}

CRendElementBase *CRenderer::EF_CreateRE( EDataType edt )
{
  CRendElementBase *re = NULL;
  switch(edt)
  {
    case eDATA_Mesh:
      re = new CREMeshImpl;
      break;

    case eDATA_Imposter:
      re = new CREImposter;
      break;

    case eDATA_HDRProcess:
      re = new CREHDRProcess;
      break;

    case eDATA_DeferredShading:
      re = new CREDeferredShading;
      break;

    case eDATA_OcclusionQuery:
      re = new CREOcclusionQuery;
      break;

    case eDATA_Flare:
      re = new CREFlare;
      break;

    case eDATA_Cloud:
      re = new CRECloud;
      break;

    case eDATA_Sky:
      re = new CRESky;
      break;

		case eDATA_HDRSky:
			re = new CREHDRSky;
			break;

    case eDATA_Beam:
      re = new CREBeam;
      break;

    case eDATA_FarTreeSprites:
      re = new CREFarTreeSprites;
      break;

    case eDATA_PostProcess:
			re = new CREPostProcess;
      break;
      
		case eDATA_FogVolume:
			re = new CREFogVolume;
			break;

		case eDATA_WaterVolume:
			re = new CREWaterVolume;
			break;

    case eDATA_WaterOcean:
      re = new CREWaterOcean;
      break;

		case eDATA_VolumeObject:
			re = new CREVolumeObject;
			break;

		case eDATA_LightPropagationVolume:
			re = new CRELightPropagationVolume;
			break;

#if !defined(EXCLUDE_DOCUMENTATION_PURPOSE)
		case eDATA_PrismObject:
			re = new CREPrismObject;
			break;
#endif // EXCLUDE_DOCUMENTATION_PURPOSE

		case eDATA_GameEffect:
			re = new CREGameEffect;
			break;
	
		case eDATA_LightShape:
			re = new CRELightShape;
			break;

		case eDATA_BreakableGlass:
			re = new CREBreakableGlass;
			break;
  }
  return re;
}

CRenderObject::~CRenderObject()
{	
  /*if (m_ShaderParams && m_bShaderParamCreatedInRenderer)
  {
    m_bShaderParamCreatedInRenderer = false;
    delete m_ShaderParams;
  }*/
}

SRenderObjData *CRenderObject::m_pPermObjData;
int CRenderObject::m_nPermObjDataID;
TArray<int> CRenderObject::m_sFreePermObjData;

void CRenderObject::Tick()
{
  CRenderer *rd = gRenDev;
	ASSERT_IS_MAIN_THREAD(rd->m_pRT)
	int nFrame = rd->m_RP.m_TI[rd->m_RP.m_nFillThreadID].m_nFrameUpdateID - 3;
  FlushFreeObjects(nFrame & 3);
}

void CRenderObject::FlushFreeObjects(int list)
{
  CRenderer *rd = gRenDev;
  TArray<CRenderObject *>& Objs = rd->m_RP.m_FreeObjects[list];
  for (uint32 i=0; i<Objs.Num(); i++)
  {
    CRenderObject *pObj = Objs[i];
    pObj->m_ObjFlags |= FOB_REMOVED;
    if (pObj->GetObjDataId()>=0)
    {
      m_sFreePermObjData.push_back(pObj->GetObjDataId());
      SRenderObjData *pOD = &m_pPermObjData[pObj->GetObjDataId()];
      if (pOD->m_pRE && pOD->m_pRE->mfGetType() == eDATA_OcclusionQuery)
      {
        pOD->m_pRE->Release(true);
        pOD->m_pRE = NULL;
      }
      pObj->SetObjDataId(-1);
    }
#if defined (DIRECT3D10) || defined(PS3)
    if (pObj->m_nCBID >= 0)
    {
      rd->m_pRT->RC_ReleaseCB_SI(pObj->m_nCBID);
      pObj->m_nCBID = -1;
    }
#endif
    assert(rd->m_RP.m_Objects[pObj->m_Id] == pObj);

		//Keep track of object IDs which are available, prevent search the entire list
		rd->m_RP.m_AvailableObjects.push_back(pObj->m_Id);
  }
  Objs.SetUse(0);
}

void CRenderer::EF_ObjRemovePermanent(CRenderObject *pObj)
{
  CRenderObject *pObjStorage = m_RP.m_Objects[pObj->m_Id];
  assert(pObj == pObjStorage);
  if (pObj != pObjStorage)
    return;
	int nFrame = m_RP.m_TI[m_RP.m_nFillThreadID].m_nFrameUpdateID;
  m_RP.m_FreeObjects[nFrame & 3].AddElem(pObj); 
}

SRenderObjData *CRenderer::EF_GetObjData(CRenderObject *pObj, bool bCreate)
{
	ASSERT_IS_MAIN_THREAD(m_pRT)
  if (pObj->GetObjDataId()<0)
  {
		if (!bCreate)
			return NULL;
		else
			return EF_GetObjData_HandleInvalidObjId(pObj, bCreate);
  }
  return pObj->GetObjData(m_RP.m_nFillThreadID);
}

SRenderObjData *CRenderer::EF_GetObjData_HandleInvalidObjId(CRenderObject *pObj, bool bCreate)
{
	ASSERT_IS_MAIN_THREAD(gRenDev->m_pRT);
  if (pObj->m_ObjFlags & FOB_PERMANENT)
	{
		int n, nID;
		if (n=CRenderObject::m_sFreePermObjData.size())
		{
			nID = CRenderObject::m_sFreePermObjData[n-1];
			CRenderObject::m_sFreePermObjData.pop_back();
		}
		else
			nID = CRenderObject::m_nPermObjDataID++;
		assert(nID < MAX_PERM_OBJECTS && nID>=0);
		nID &= (MAX_PERM_OBJECTS-1);
		pObj->SetObjDataId(nID);
		CRenderObject::m_pPermObjData[nID].Init();
 		return &CRenderObject::m_pPermObjData[nID];
	}
	else
	{
		int nThreadID = m_RP.m_nFillThreadID;
		pObj->SetObjDataId(ObjData(nThreadID).size());
		SRenderObjData *pD = ObjData(nThreadID).AddIndex(1);
		memset(pD, 0, sizeof(SRenderObjData));
		pD->m_FogVolumeContribIdx[nThreadID] = -1;
		return pD;
	}
}

SRenderObjData *CRenderer::FX_GetObjData(CRenderObject *pObj)
{
  ASSERT_IS_RENDER_THREAD(gRenDev->m_pRT);
  IF (pObj->GetObjDataId()<0,0)
      return NULL;
  int nThreadID = m_pRT->GetThreadList();
  return pObj->GetObjData(nThreadID);
}

void CRenderObject::CopyTo(CRenderObject *pObjNew)
{
	ASSERT_IS_MAIN_THREAD(gRenDev->m_pRT)
	pObjNew->CloneObject(this);
  if (!(m_ObjFlags & FOB_PERMANENT))
    pObjNew->SetObjDataId(m_nObjDataId);
  else
  {
    pObjNew->SetObjDataId(-1);
    pObjNew->m_ObjFlags &= ~(FOB_PERMANENT | FOB_REMOVED);
    SRenderObjData *pOD = GetObjData(gRenDev->m_RP.m_nFillThreadID);
    if (pOD)
    {
      SRenderObjData *pODNew = gRenDev->EF_GetObjData(pObjNew, true);
      *pODNew = *pOD;
    }
  }
}


CRenderObject *CRenderer::EF_GetObject_Index(int index)
{
	CRenderObject *obj;
	assert(index>=0);

  ASSERT_IS_MAIN_THREAD(m_pRT);
  int nThreadID = m_RP.m_nFillThreadID;
  obj = m_RP.m_Objects[index];
  if (!(obj->m_ObjFlags & FOB_PERMANENT))
			obj->SetObjDataId(-1); 
	SRenderObjData* pOD = obj->GetObjData(nThreadID);
  if (pOD)
    pOD->m_FogVolumeContribIdx[nThreadID] = (uint16) -1;
  return obj;
}


CRenderObject *CRenderer::EF_GetObject_Perm()
{
	CRenderObject *obj;

	ASSERT_IS_MAIN_THREAD(m_pRT)

	int nThreadID = m_RP.m_nFillThreadID;

	TArray <CRenderObject *>& Objs = m_RP.m_Objects;
	uint32 n = Objs.Num();

	//query free list first
	TArray <uint16>& availableObjs = m_RP.m_AvailableObjects;
	int nAvailable = availableObjs.Num();

	if(nAvailable)
	{
		uint32 index = availableObjs[nAvailable-1];
		availableObjs.pop_back();

		//Debug Code
		//make sure this obj hasn't been reallocated somewhere
		//if(!(Objs[index]->m_ObjFlags & FOB_REMOVED))
		//{
			//CryFatalError("Available object list contains an object which has been re-allocated");
		//}

		Objs[index]->m_ObjFlags &= ~FOB_REMOVED;
		n = index;
		obj = Objs[n];
	}
	else
	{
		Objs.GrowReset(1);

		obj = new CRenderObject;
		Objs[n] = obj;

		obj->m_ObjFlags |= FOB_PERMANENT;
	}


	obj->AssignId(n);
	obj->Init(nThreadID);

	return obj;
}

CRenderObject *CRenderer::EF_GetObject_Temp()
{
	CRenderObject *obj;
	uint32 i;

	ASSERT_IS_MAIN_THREAD(m_pRT)

		int nThreadID = m_RP.m_nFillThreadID;

	TArray <CRenderObject *>& Objs = m_RP.m_TempObjects[nThreadID];
	uint32 n = Objs.Num();
	if (i=m_RP.m_RejectedObjects[nThreadID].Num())
	{
		i--; 
		obj = m_RP.m_RejectedObjects[nThreadID][i];
		m_RP.m_RejectedObjects[nThreadID].SetUse(i);
		obj->Init(nThreadID);
		assert (!(obj->m_ObjFlags & FOB_PERMANENT));
		return obj;
	}

	Objs.GrowReset(1);

	obj = Objs[n];
  bool created = false; 

	if (!obj)
	{
		obj = new CRenderObject;
		Objs[n] = obj;
    created = true; 
	}

	assert (!(obj->m_ObjFlags & FOB_PERMANENT));





	obj->AssignId(n);
	obj->Init(nThreadID);

	return obj;
}

CRenderObject *CRenderer::EF_DuplicateRO(CRenderObject *pObj, const SRenderObjectModifier * pROII)
{
  CRenderer *rd = this;
  CRenderObject * pObjNew = rd->EF_GetObject_Temp();

  pObj->CopyTo(pObjNew);

  SRenderObjData *pOD = NULL;
  if (pROII && pROII->nMatricesInUse)
  {
    pObjNew->m_II.m_Matrix = pROII->mat;
		uint32 nThreadID = rd->m_RP.m_nFillThreadID;

		pOD = pObj->GetObjData(nThreadID);
		if (pOD && pOD->m_pInstance && !(rd->m_RP.m_TI[nThreadID].m_PersFlags & RBPF_SHADOWGEN) )
		{
			pObjNew->SetObjDataId(-1);
			void *pOD_Instace = pOD->m_pInstance; // store instance before EF_GetObjData could reallocate the arrat pOD is pointing to
			ISkinnable *pOD_CharInstace = pOD->m_pCharInstance;
			uint8 pOD_ObjID = pOD->m_nObjID;
			SRenderObjData *pODNew = rd->EF_GetObjData(pObjNew, true);
			pODNew->m_pInstance = pOD_Instace;
			pODNew->m_pCharInstance = pOD_CharInstace;
			pODNew->m_nObjID	=	(uint8)pROII->nSubObjId;//pOD_ObjID;
			
		}

    if( !pROII->mat.m01 && !pROII->mat.m02 && !pROII->mat.m10 && !pROII->mat.m12 && !pROII->mat.m20 && !pROII->mat.m21 )
      pObjNew->m_ObjFlags &= ~FOB_TRANS_ROTATE;
    else
      pObjNew->m_ObjFlags |= FOB_TRANS_ROTATE;
  }

  return pObjNew;
}


float CRenderer::EF_GetWaterZElevation(float fX, float fY)
{
  I3DEngine *eng = (I3DEngine *)gEnv->p3DEngine;
  if (!eng)
    return 0;
  return eng->GetWaterLevel();
}

void CRenderer::EF_RemovePolysFromScene()
{  
  ASSERT_IS_MAIN_THREAD(m_pRT)

  for (int i=0; i<MAX_RECURSION_LEVELS; i++)
  {
    CREClientPoly::m_PolysStorage[m_RP.m_nFillThreadID][i].SetUse(0);
  }
  m_RP.m_SysVertexPool[m_RP.m_nFillThreadID].SetUse(0);
  m_RP.m_SysIndexPool[m_RP.m_nFillThreadID].SetUse(0);
  m_RP.m_Polygons.SetUse(0);
}

CRenderObject *CRenderer::MergePolygonRO(CRenderObject* pRO)
{
	uint32 i;

	if (pRO)
	{
		SRefSprite *rs = NULL;
		for (i=0; i<m_RP.m_Polygons.Num(); i++)
		{
			rs = &m_RP.m_Polygons[i];
			if (pRO == rs->m_pObj)
				break;
		}
		if (i == m_RP.m_Polygons.Num())
		{
			for (i=0; i<m_RP.m_Polygons.Num(); i++)
			{
				rs = &m_RP.m_Polygons[i];
				if (rs->m_pObj->m_DynLMMask[m_RP.m_nFillThreadID] == pRO->m_DynLMMask[m_RP.m_nFillThreadID] && rs->m_pObj->m_RState == pRO->m_RState && rs->m_pObj->m_fSort == pRO->m_fSort &&
					rs->m_pObj->m_II.m_AmbColor == pRO->m_II.m_AmbColor && rs->m_pObj->m_fAlpha == pRO->m_fAlpha)
				{
					m_RP.m_RejectedObjects[m_RP.m_nFillThreadID].AddElem(pRO);
					pRO = rs->m_pObj;
					break;
				}
			}
			if (i == m_RP.m_Polygons.Num())
			{
				SRefSprite s;
				s.m_pObj = pRO;
				//obj->m_Matrix.SetIdentity();
				m_RP.m_Polygons.AddElem(s);
				rs = &m_RP.m_Polygons[m_RP.m_Polygons.Num()-1];
			}
		}
	} 

	return pRO;
}

CRenderObject *CRenderer::EF_AddPolygonToScene(SShaderItem& si, int numPts, const SVF_P3F_C4B_T2F *verts, const SPipTangents *tangs, CRenderObject *obj, uint16 *inds, int ninds, int nAW, bool /*bMerge*/)
{
  ASSERT_IS_MAIN_THREAD(m_pRT)
  int nThreadID = m_RP.m_nFillThreadID;
	const uint32 nPersFlags = m_RP.m_TI[nThreadID].m_PersFlags;

  assert(si.m_pShader && si.m_pShaderResources);
  if (!si.m_pShader || !si.m_pShaderResources)
  {
    Warning("CRenderer::EF_AddPolygonToScene without shader...");
    return NULL;
  }
  if (si.m_nPreprocessFlags == -1)
  {
    if (!si.Update())
      return obj;
  }

//  /// Workaround on PS3 to fix decals flickering
//#ifndef PS3
//	if (bMerge)
//		obj = MergePolygonRO(obj);
//#endif

  int nR = SRendItem::m_RecurseLevel[nThreadID]-1;
	if (nR < 0) return NULL;

  int num = CREClientPoly::m_PolysStorage[nThreadID][nR].Num();
  CREClientPoly::m_PolysStorage[nThreadID][nR].GrowReset(1);

  CREClientPoly *pl = CREClientPoly::m_PolysStorage[nThreadID][nR][num];
  if (!pl)
  {
    pl = new CREClientPoly;
    CREClientPoly::m_PolysStorage[nThreadID][nR][num] = pl;
  }

  pl->m_Shader = si;
  pl->m_sNumVerts = numPts;
  pl->m_pObject = obj;
	pl->m_nCPFlags = 0;
	if(nAW)
		pl->m_nCPFlags |= CREClientPoly::efAfterWater;
	if(nPersFlags & RBPF_SHADOWGEN)
		pl->m_nCPFlags |= CREClientPoly::efShadowGen;

  int nSize = CRenderMesh::m_cSizeVF[eVF_P3F_C4B_T2F] * numPts;
  int nOffs = m_RP.m_SysVertexPool[nThreadID].Num();
  SVF_P3F_C4B_T2F *vt = (SVF_P3F_C4B_T2F *)m_RP.m_SysVertexPool[nThreadID].GrowReset(nSize);
  pl->m_nOffsVert = nOffs;
  for (int i=0; i<numPts; i++, vt++)
  {
    vt->xyz = verts[i].xyz;
    vt->st = verts[i].st;
    vt->color.dcolor = verts[i].color.dcolor;
  }
  if (tangs)
  {
    nSize = sizeof(SPipTangents) * numPts;
    nOffs = m_RP.m_SysVertexPool[nThreadID].Num();
    SPipTangents *t = (SPipTangents *)m_RP.m_SysVertexPool[nThreadID].GrowReset(nSize);
    pl->m_nOffsTang = nOffs;
    for (int i=0; i<numPts; i++, t++)
    {
      *t = tangs[i];
    }
  }
  else
    pl->m_nOffsTang = -1;


  pl->m_nOffsInd = m_RP.m_SysIndexPool[nThreadID].Num();

  if (inds && ninds)
  {
    uint16* dstind = m_RP.m_SysIndexPool[nThreadID].Grow(ninds);
    memcpy(dstind, inds, ninds*sizeof(uint16));
    pl->m_sNumIndices = ninds;
  }
  else
  {
    uint16* dstind = m_RP.m_SysIndexPool[nThreadID].Grow((numPts-2) * 3);
    for (int i=0; i<numPts-2; i++, dstind+=3)
    {
      dstind[0] = 0;
      dstind[1] = i+1;
      dstind[2] = i+2;
    }
    pl->m_sNumIndices = (numPts-2) * 3;
  }

  return obj;
}

CRenderObject* CRenderer::EF_AddPolygonToScene(SShaderItem& si, CRenderObject* obj, int numPts, int ninds, SVF_P3F_C4B_T2F*& verts, SPipTangents*& tangs, uint16*& inds, int nAW, bool /*bMerge*/)
{
  ASSERT_IS_MAIN_THREAD(m_pRT)
  int nThreadID = m_RP.m_nFillThreadID;
	const uint32 nPersFlags = m_RP.m_TI[nThreadID].m_PersFlags;

  assert(si.m_pShader && si.m_pShaderResources);
  if (!si.m_pShader || !si.m_pShaderResources)
  {
    Warning("CRenderer::EF_AddPolygonToScene without shader...");
    return NULL;
  }
  if (si.m_nPreprocessFlags == -1)
  {
    if (!si.Update())
      return obj;
  }

	//if (bMerge)
	//	obj = MergePolygonRO(obj);
  int nR = SRendItem::m_RecurseLevel[nThreadID]-1;
# ifndef _RELEASE
  if (nR<0) __debugbreak();
# endif 
	int num = CREClientPoly::m_PolysStorage[nThreadID][nR].Num();
	CREClientPoly::m_PolysStorage[nThreadID][nR].GrowReset(1);

	CREClientPoly *pl = CREClientPoly::m_PolysStorage[nThreadID][nR][num];
	if (!pl)
	{
		pl = new CREClientPoly;
		CREClientPoly::m_PolysStorage[nThreadID][nR][num] = pl;
	}

	pl->m_Shader = si;
	pl->m_pObject = obj;
	if(nAW)
		pl->m_nCPFlags |= CREClientPoly::efAfterWater;
	if(nPersFlags & RBPF_SHADOWGEN)
		pl->m_nCPFlags |= CREClientPoly::efShadowGen;

	//////////////////////////////////////////////////////////////////////////
	// allocate buffer space for caller to fill

	pl->m_sNumVerts = numPts;
	pl->m_nOffsVert = m_RP.m_SysVertexPool[nThreadID].Num();
	pl->m_nOffsTang = m_RP.m_SysVertexPool[nThreadID].Num() + sizeof(SVF_P3F_C4B_T2F) * numPts;
	m_RP.m_SysVertexPool[nThreadID].GrowReset( (sizeof(SVF_P3F_C4B_T2F) + sizeof(SPipTangents)) * numPts );
	verts = (SVF_P3F_C4B_T2F*) &m_RP.m_SysVertexPool[nThreadID][pl->m_nOffsVert];
	tangs = (SPipTangents*) &m_RP.m_SysVertexPool[nThreadID][pl->m_nOffsTang];

	pl->m_sNumIndices = ninds;
	pl->m_nOffsInd = m_RP.m_SysIndexPool[nThreadID].Num();
	inds = (uint16*) m_RP.m_SysIndexPool[nThreadID].Grow(ninds);

	//////////////////////////////////////////////////////////////////////////

	return obj;
}

//////////////////////////////////////////////////////////////////////////
CREParticle* CRenderer::EF_AddParticlesToScene(const SAddParticlesToSceneJob& job, const CCamera& cam)
{
  FUNCTION_PROFILER_FAST( GetISystem(),PROFILE_PARTICLE,g_bProfilerEnabled );
  ASSERT_IS_MAIN_THREAD(m_pRT)
	
	int nThreadFill = gRenDev->m_pRT->CurThreadFill();

	CREParticle* pRE = CREParticle::Create(job.pPVC, cam, nThreadFill);
	if (pRE)
  {
		pRE->m_CustomTexBind[0] = job.nCustomTexId > 0 ? job.nCustomTexId : -1;
		pRE->mfSetFlags(job.nRenderElemFlags);

		m_RP.m_ParticleJobs[nThreadFill].push_back(job);
		m_RP.m_ParticleJobs[nThreadFill].back().pREParticle = pRE;
	}
	return pRE;
}

int SParticleAddJobCompare::m_nThreadList = 0;
int SParticleAddJobCompare::m_nFillThread = 0;
CRenderer const * SParticleAddJobCompare::m_pRenderer = NULL;

TArray<SParticleAddJobCompare> SParticleAddJobCompare::m_arrSortedJobs;

void CRenderer::EF_ProcessAddedParticles()
{
  FUNCTION_PROFILER_FAST( GetISystem(),PROFILE_PARTICLE,g_bProfilerEnabled );
  ASSERT_IS_MAIN_THREAD(m_pRT)

	int nThreadFill = gRenDev->m_pRT->CurThreadFill();
	PodArray<SAddParticlesToSceneJob>& ParticleJobs = m_RP.m_ParticleJobs[nThreadFill];
	size_t nJobs = ParticleJobs.size();
	
	SParticleAddJobCompare::m_arrSortedJobs.resize(0);

	// Check half-res coverage threshold
	float fHalfResCoverageThreshold = (float)CV_r_useparticles_halfres_min_coverage / (GetCamera().GetFov() * GetCamera().GetHorizontalFov());
	if (CV_r_useparticles_halfres)
	{
		uint8 nHalfResBlendFlag = CV_r_useparticles_halfres == 2 ? OS_ALPHA_BLEND : OS_ADD_BLEND;
		for (size_t i = 0; i < nJobs; i++)
		{
			SAddParticlesToSceneJob& job = ParticleJobs[i];

			// Validate halfres flag
			if ((job.eAllowHalfRes || CV_r_useparticles_halfres_force)
				&& (job.pRenderObject->m_RState & nHalfResBlendFlag)
				&& job.bAfterWater)
			{
				if (job.eAllowHalfRes == SAddParticlesToSceneJob::eHalfResForce)
					fHalfResCoverageThreshold = 0.f;
				else
				{
					job.eAllowHalfRes = SAddParticlesToSceneJob::eHalfResAllow;
					if (fHalfResCoverageThreshold > 0.f)
						fHalfResCoverageThreshold -= div_min(job.pPVC->GetApproxParticleArea(), sqr(job.pRenderObject->m_fDistance), fHalfResCoverageThreshold);
				}
			}
			else
				job.eAllowHalfRes = SAddParticlesToSceneJob::eHalfResNotAllow;
		}
	}

	if (CV_r_useparticles_merge)
	{
		SParticleAddJobCompare::m_nThreadList = nThreadFill;
		SParticleAddJobCompare::m_nFillThread = m_RP.m_nFillThreadID;
		SParticleAddJobCompare::m_pRenderer = this;

		SParticleAddJobCompare::m_arrSortedJobs.resize(nJobs);
		for (size_t i = 0; i < nJobs; i++)
			SParticleAddJobCompare::m_arrSortedJobs[i] = SParticleAddJobCompare(&ParticleJobs[i]);

		// Group emitters according to their states
		std::sort(SParticleAddJobCompare::m_arrSortedJobs.begin(), SParticleAddJobCompare::m_arrSortedJobs.end(), SParticleAddJobCompare());

		// Merge particle render objects
		for (size_t i = 1; i < nJobs; i++)
		{
			if (SParticleAddJobCompare::Mergeable(SParticleAddJobCompare::m_arrSortedJobs[i-1], SParticleAddJobCompare::m_arrSortedJobs[i]))
			{
				SAddParticlesToSceneJob * pJobA = SParticleAddJobCompare::m_arrSortedJobs[i-1].m_pJob;
				SAddParticlesToSceneJob * pJobB = SParticleAddJobCompare::m_arrSortedJobs[i].m_pJob;

				if (CV_r_useparticles_merge < 2 || pJobA->pRenderObject->m_fDistance < pJobB->pRenderObject->m_fDistance)
					pJobB->pRenderObject = pJobA->pRenderObject;
				else
					pJobA->pRenderObject = pJobB->pRenderObject;
				pJobA->pRenderObject->m_fDistance = min(pJobA->pRenderObject->m_fDistance, pJobB->pRenderObject->m_fDistance);;
			}
		}

		// Sort groups by distance
		std::sort(SParticleAddJobCompare::m_arrSortedJobs.begin(), SParticleAddJobCompare::m_arrSortedJobs.end(), SParticleAddJobCompare::BackToFrontCmp);
	}

	for (size_t i = 0; i < nJobs; ++ i)
	{
		const SAddParticlesToSceneJob& job = CV_r_useparticles_merge ? *SParticleAddJobCompare::m_arrSortedJobs[i].m_pJob : ParticleJobs[i];

		if (job.pShaderItem->m_nPreprocessFlags == -1)
		{
			if (!job.pShaderItem->Update())
				continue;
		}

		SShaderItem shaderItem(*job.pShaderItem);

#if defined(DIRECT3D10) && !defined(PS3) // PS3 doesn't support geometry shader
		SShaderTechnique* pTech = shaderItem.GetTechnique();
		if (pTech && (pTech->m_Flags & FHF_USE_GEOMETRY_SHADER) != 0)
		{
			if (!CV_r_UseGSParticles || !(job.nRenderElemFlags & FCEF_GEOM_SHADER))
				shaderItem.m_nTechnique = shaderItem.m_nTechnique >= 0 ? shaderItem.m_nTechnique + 1 : 1;
		}
#endif

		bool bHalfRes = fHalfResCoverageThreshold <= 0.f && job.eAllowHalfRes > 0;
		EF_AddParticle(job.pREParticle, shaderItem, job.pRenderObject, job.bAfterWater, bHalfRes);
	}

	ParticleJobs.resize(0);
}

void CRenderer::EF_AddParticle(CREParticle* pParticle, SShaderItem& shaderItem, CRenderObject* pRO, int nAW, bool bHalfRes)
{
  if (pRO && shaderItem.m_pShader)
	{
    uint32 nBatchFlags = FB_GENERAL;
    int nList = EFSLIST_TRANSP;

		if (((CShader*)shaderItem.m_pShader)->m_Flags & EF_REFRACTIVE)
		{
			if (CV_r_refraction && CV_r_useparticles_refraction)
			{
				nBatchFlags |= FB_TRANSPARENT;
				nList = EFSLIST_TRANSP;
				if (CRenderer::CV_r_RefractionPartialResolves)
					pRO->m_ObjFlags |= FOB_REQUIRES_RESOLVE;
			}
			else 
				return;  // skip adding refractive particle

			bHalfRes = false;
		}

		if (SShaderTechnique* pTech = shaderItem.GetTechnique())
		{
			if (pTech->m_nTechnique[TTYPE_CUSTOMRENDERPASS] > 0 )
			{								
				int nThreadID = m_RP.m_nFillThreadID;
				SRenderObjData *pOD = pRO->GetObjData(nThreadID);			
				const uint32 nVisionParams = (pOD && pOD->m_nVisionParams);
				if (m_nThermalVisionMode && nVisionParams)
				{
					nBatchFlags |= FB_CUSTOM_RENDER;
					//pRO->m_RState = OS_ADD_BLEND;
					bHalfRes = false;
				}
			}
		}

		if (bHalfRes)
			nList = EFSLIST_HALFRES_PARTICLES;

		SRendItem::mfAdd(m_pRT->GetThreadList(), pParticle, pRO, shaderItem, nList, nAW, nBatchFlags);    
  }
}

void CRenderer::EF_AddClientPolys()
{
  uint32 i;
  CREClientPoly *pl;

  ASSERT_IS_MAIN_THREAD(m_pRT)
  int nThreadID = m_pRT->GetThreadList();
	int nR = SRendItem::m_RecurseLevel[nThreadID]-1;
# ifndef _RELEASE
  if (nR<0) __debugbreak();
# endif 
	const SThreadInfo& rTI = m_RP.m_TI[nThreadID];
	const uint32 nPersFlags = rTI.m_PersFlags;

  for (i=0; i<CREClientPoly::m_PolysStorage[nThreadID][nR].Num(); i++)
  {
    pl = CREClientPoly::m_PolysStorage[nThreadID][nR][i];

    if (pl->m_Shader.m_nPreprocessFlags & FSPR_MASK)
      SRendItem::mfAdd(nThreadID, pl, pl->m_pObject, pl->m_Shader, EFSLIST_PREPROCESS, 0, FB_GENERAL);
    if (pl->m_Shader.m_pShader->GetFlags() & EF_DECAL) // || pl->m_pObject && (pl->m_pObject->m_ObjFlags & FOB_DECAL))
    {
      CShader *pS = (CShader *)pl->m_Shader.m_pShader;
      SRenderShaderResources *const __restrict pR = (SRenderShaderResources *)pl->m_Shader.m_pShaderResources;
      SShaderTechnique *pTech = pl->m_Shader.GetTechnique();

      uint32 nBatchFlags = FB_GENERAL;
        if( pTech && pTech->m_nTechnique[TTYPE_Z] > 0 && (pS && (pS->m_Flags & EF_SUPPORTSDEFERREDSHADING) ) )
        {
          // temporary hack: if no normal map use base normal from NormalsTarget          
          // todo: make this instead by decal type
        if( pl->m_Shader.m_pShaderResources && pl->m_Shader.m_pShaderResources->GetTexture(EFTT_BUMP))
            nBatchFlags |= FB_Z;
        }

      if (pTech && pR)
			{
				if( pTech->m_nTechnique[TTYPE_GLOWPASS] > 0 && pR->Glow())
					nBatchFlags |= FB_GLOW;

				if (pTech->m_nTechnique[TTYPE_CUSTOMRENDERPASS] > 0 && m_nThermalVisionMode && pR->HeatAmount())
					nBatchFlags |= FB_CUSTOM_RENDER;
			}

			if(!(nPersFlags & RBPF_SHADOWGEN) && !(pl->m_nCPFlags & CREClientPoly::efShadowGen))
				SRendItem::mfAdd(nThreadID, pl, pl->m_pObject, pl->m_Shader, EFSLIST_DECAL, pl->m_nCPFlags & CREClientPoly::efAfterWater, nBatchFlags);
			else if((nPersFlags & RBPF_SHADOWGEN) && (pl->m_nCPFlags & CREClientPoly::efShadowGen))
				SRendItem::mfAdd(nThreadID, pl, pl->m_pObject, pl->m_Shader, EFSLIST_SHADOW_GEN, SG_SORT_GROUP, FB_GENERAL);
    }
    else
		{
			uint32 list = EFSLIST_GENERAL;
			if (pl->m_pObject->m_fAlpha < 1.0f || pl->m_Shader.m_pShaderResources->GetOpacity() < 1.0f)
			{
				list = EFSLIST_TRANSP;
			}
			SRendItem::mfAdd(nThreadID, pl, pl->m_pObject, pl->m_Shader, list, pl->m_nCPFlags & CREClientPoly::efAfterWater, FB_GENERAL);
		}
  }
}


// Dynamic lights
bool CRenderer::EF_IsFakeDLight(const CDLight *Source)
{
  if (!Source)
  {
    iLog->Log("Warning: EF_IsFakeDLight: NULL light source\n");
    return true;
  }

  bool bIgnore = false;
  if (Source->m_Flags & (DLF_DEFERRED_LIGHT|DLF_FAKE))
    bIgnore = true;

  return bIgnore;
}

void CRenderer::EF_CheckLightMaterial(CDLight *Source, SRenderLight *pNewLight)
{
  ASSERT_IS_MAIN_THREAD(m_pRT);
	int nThreadID = m_RP.m_nFillThreadID;
	int nR = SRendItem::m_RecurseLevel[nThreadID]-1;
# ifndef _RELEASE
  if (nR<0) __debugbreak();
# endif 
	if (!(m_RP.m_TI[nThreadID].m_PersFlags & RBPF_IMPOSTERGEN))
	{
		// Add light coronas, lens flares, beams and so on (depends on shader)
		if (Source->m_Shader.m_pShader && Source->m_Shader.m_pShader->GetREs(Source->m_Shader.m_nTechnique) && Source->m_Shader.m_pShader->GetREs(Source->m_Shader.m_nTechnique)->Num())
		{
			I3DEngine *eng = (I3DEngine *)gEnv->p3DEngine;
			float fWaterLevel = eng->GetWaterLevel();
			float fCamZ = m_RP.m_TI[nThreadID].m_cam.GetPosition().z;
			//get the permanent object
			if (!Source->m_pObject[nR])
			{         
				Source->m_pObject[nR] = EF_GetObject_Perm();
				Source->m_pObject[nR]->m_fAlpha = 1.0f;
				Source->m_pObject[nR]->m_II.m_AmbColor = Vec3(0,0,0);
				SRenderObjData *pOD = EF_GetObjData(Source->m_pObject[nR], true);
				pOD->m_fTempVars[0] = 0;
				pOD->m_fTempVars[1] = 0;
				pOD->m_fTempVars[3] = Source->m_fRadius;
			}
			else
				EF_GetObject_Index(Source->m_pObject[nR]->m_Id);	

			if (pNewLight)
				pNewLight->m_pObject[nR] = Source->m_pObject[nR];

			SRenderObjData *pOD = EF_GetObjData(Source->m_pObject[nR], true);

			CRendElementBase *pRE = Source->m_Shader.m_pShader->GetREs(Source->m_Shader.m_nTechnique)->Get(0);
			float fCustomSort = 0;
			if (pRE->mfGetType() == eDATA_Flare)
			{          
				Source->m_pObject[nR]->m_II.m_AmbColor.r = Source->m_Color.r;
				Source->m_pObject[nR]->m_II.m_AmbColor.g = Source->m_Color.g;
				Source->m_pObject[nR]->m_II.m_AmbColor.b = Source->m_Color.b;
				fCustomSort = 4000.0f;
			}
			else
			{
				Source->m_pObject[nR]->m_II.m_AmbColor = Source->m_Color;
				pOD->m_fTempVars[3] = Source->m_fRadius;
			}

			Source->m_pObject[nR]->m_II.m_Matrix = Source->m_ObjMatrix;
			pOD->m_pLight = Source;
			Source->m_pObject[nR]->m_DynLMMask[nThreadID] = 1<<Source->m_Id;
			Source->m_pObject[nR]->m_ObjFlags |= FOB_TRANS_MASK;

			UINT nList = EFSLIST_TRANSP;
			int nAW = 0;
			if((fCamZ-fWaterLevel)*(Source->m_Origin.z-fWaterLevel)>0)
				nAW = 1;
			else
				nAW = 0;
			EF_AddEf(pRE, Source->m_Shader, Source->m_pObject[nR], nList, nAW);
		}
	}
}

void CRenderer::EF_ADDDlight(CDLight *Source)
{
  if (!Source)
  {
    iLog->Log("Warning: EF_ADDDlight: NULL light source\n");
    return;
  }

  ASSERT_IS_MAIN_THREAD(m_pRT)

  bool bIgnore = EF_IsFakeDLight(Source);
  //Source->m_Flags &= ~DLF_POINT;
  //Source->m_Flags |= DLF_DIRECTIONAL;

  int nThreadID = m_RP.m_nFillThreadID;
  int nR = SRendItem::m_RecurseLevel[nThreadID]-1;
	#ifndef _RELEASE
  if (nR<0) __debugbreak();
  #endif 

  SRenderLight *pNew = NULL;
  if (bIgnore)
    Source->m_Id = -1;
  else
  {
    assert((Source->m_Flags & DLF_LIGHTTYPE_MASK) != 0);
    Source->m_Id = m_RP.m_DLights[nThreadID][nR].Num();
    if (Source->m_Id >= 32)
    {
      //iLog->Log("Warning: EF_ADDDlight: Too many light sources (Ignored)\n");
      Source->m_Id = -1;
      return;
    }
    pNew = m_RP.m_DLights[nThreadID][nR].AddIndex(1); 
    memcpy(pNew, Source, sizeof(SRenderLight));
  }
  EF_PrecacheResource(Source, (m_RP.m_TI[nThreadID].m_cam.GetPosition()-Source->m_Origin).GetLengthSquared() / max(0.001f, Source->m_fRadius * Source->m_fRadius), 0.1f, 0, 0);

  EF_CheckLightMaterial(Source, pNew);
}

bool CRenderer::EF_AddDeferrredDecal( const SDeferrredDecal & rDecal )
{
  ASSERT_IS_MAIN_THREAD(m_pRT)

  int nThreadID = m_RP.m_nFillThreadID;
  int nR = SRendItem::m_RecurseLevel[nThreadID]-1;

	assert(nR>=0);
	if (nR<0)
	{
		iLog->Log("Warning: CRenderer::EF_AddDeferrredDecal: decal adding before calling EF_StartEf");
		return false;
	}

  if(m_RP.m_DeferrredDecals[nThreadID][nR].Num()<1024)
  {
    m_RP.m_DeferrredDecals[nThreadID][nR].AddElem(rDecal);
    int nLastElem = m_RP.m_DeferrredDecals[nThreadID][nR].Num()-1;

    SDeferrredDecal& rDecalCopy = m_RP.m_DeferrredDecals[nThreadID][nR].Get(nLastElem);

    //////////////////////////////////////////////////////////////////////////
    IMaterial* pDecalMaterial = rDecalCopy.pMaterial;
    if (pDecalMaterial==NULL)
    {
      assert(0);
      return false;
    }

    SShaderItem& sItem = pDecalMaterial->GetShaderItem(0);
    if (sItem.m_pShaderResources==NULL)
    {
      assert(0);
      return false;
    }

    if(SEfResTexture* pNormalRes0= sItem.m_pShaderResources->GetTexture(EFTT_BUMP))
    {
      if(pNormalRes0->m_Sampler.m_pITex)
      {
        rDecalCopy.nFlags |= DECAL_HAS_NORMAL_MAP;
				m_RP.m_isDeferrredNormalDecals[nThreadID][nR] = true;
      }
      else
      {
        rDecalCopy.nFlags &= ~DECAL_HAS_NORMAL_MAP;
      }
    }

		if(SEfResTexture* pSpecularRes0= sItem.m_pShaderResources->GetTexture(EFTT_GLOSS))
		{
			if(pSpecularRes0->m_Sampler.m_pITex)
			{
				rDecalCopy.nFlags |= DECAL_HAS_SPECULAR_MAP;
			}
			else
			{
				rDecalCopy.nFlags &= ~DECAL_HAS_SPECULAR_MAP;
			}
		}
    //////////////////////////////////////////////////////////////////////////

    if(CV_r_deferredDecalsDebug)
    {
      Vec3 vCenter = rDecalCopy.projMatrix.GetTranslation();
      float fSize = rDecalCopy.projMatrix.GetColumn(2).GetLength();
      Vec3 vSize(fSize,fSize,fSize);
      AABB aabbCenter(vCenter-vSize*0.05f, vCenter+vSize*0.05f);
      GetIRenderAuxGeom()->DrawAABB(aabbCenter, false, Col_Yellow, eBBD_Faceted);
      GetIRenderAuxGeom()->DrawLine(vCenter, Col_Red,   vCenter+rDecalCopy.projMatrix.GetColumn(0), Col_Red);
      GetIRenderAuxGeom()->DrawLine(vCenter, Col_Green, vCenter+rDecalCopy.projMatrix.GetColumn(1), Col_Green);
      GetIRenderAuxGeom()->DrawLine(vCenter, Col_Blue,  vCenter+rDecalCopy.projMatrix.GetColumn(2), Col_Blue);
    }

    return true;
  }
  return false;
}

void CRenderer::EF_ClearLightsList()
{
  ASSERT_IS_MAIN_THREAD(m_pRT)
# ifndef _RELEASE
  if (SRendItem::m_RecurseLevel[m_RP.m_nFillThreadID] == 0) __debugbreak();
# endif
  m_RP.m_DLights[m_RP.m_nFillThreadID][SRendItem::m_RecurseLevel[m_RP.m_nFillThreadID]-1].SetUse(0);
  m_RP.m_SMFrustums[m_RP.m_nFillThreadID][SRendItem::m_RecurseLevel[m_RP.m_nFillThreadID]-1].SetUse(0);
}

inline Matrix44	ToLightMatrix(const Ang3 &angle)	{
	Matrix33 ViewMatZ=Matrix33::CreateRotationZ(-angle.x);
	Matrix33 ViewMatX=Matrix33::CreateRotationX(-angle.y);
	Matrix33 ViewMatY=Matrix33::CreateRotationY(+angle.z);
	return GetTransposed44(Matrix44(ViewMatX*ViewMatY*ViewMatZ));
}

bool CRenderer::EF_UpdateDLight(SRenderLight *dl)
{
  if (!dl)
    return false;

  float fTime = iTimer->GetCurrTime() * dl->m_fAnimSpeed;

  uint32 nStyle = dl->m_nLightStyle;
	if (dl->m_pLightAnimationNode)
	{
		//TODO: This may require further optimizations.
		const IAnimNode *pLightAnimNode = dl->m_pLightAnimationNode;
		IAnimTrack *pPosTrack = pLightAnimNode->GetTrackForParameter(APARAM_POS);
		IAnimTrack *pRotTrack = pLightAnimNode->GetTrackForParameter(APARAM_ROT);
		IAnimTrack *pColorTrack = pLightAnimNode->GetTrackForParameter(APARAM_LIGHT_DIFFUSECOLOR);
		IAnimTrack *pDiffMultTrack = pLightAnimNode->GetTrackForParameter(APARAM_LIGHT_DIFFUSEMULTIPLIER);
		IAnimTrack *pRadiusTrack = pLightAnimNode->GetTrackForParameter(APARAM_LIGHT_RADIUS);
		IAnimTrack *pSpecMultTrack = pLightAnimNode->GetTrackForParameter(APARAM_LIGHT_SPECULARMULTIPLIER);
		IAnimTrack *pHDRDynamicTrack = pLightAnimNode->GetTrackForParameter(APARAM_LIGHT_HDRDYNAMIC);

		Range timeRange = const_cast<IAnimNode*>(pLightAnimNode)->GetSequence()->GetTimeRange();
		float time = dl->m_bTimeScrubbingInTrackView ? dl->m_fTimeScrubbed : fTime;
		float phase = static_cast<float>(dl->m_nLightPhase) / 100.0f;
		
		if (pPosTrack && pPosTrack->GetNumKeys() > 0)
		{
			Vec3 vOffset(0, 0, 0);
			float duration = max(pPosTrack->GetKeyTime(pPosTrack->GetNumKeys()-1), 0.001f);
			float timeNormalized = static_cast<float>(fmod(time+phase*duration, duration));
			pPosTrack->GetValue(timeNormalized, vOffset);
			dl->m_Origin = dl->m_BaseOrigin + vOffset;
		}
		
		if (pRotTrack && pRotTrack->GetNumKeys() > 0)
		{
			Vec3 vRot(0, 0, 0);
			float duration = max(pRotTrack->GetKeyTime(pRotTrack->GetNumKeys()-1), 0.001f);
			float timeNormalized = static_cast<float>(fmod(time+phase*duration, duration));
			pRotTrack->GetValue(timeNormalized, vRot);
			static_cast<CDLight*>(dl)->SetMatrix(
				dl->m_BaseObjMatrix * Matrix34::CreateRotationXYZ(Ang3(DEG2RAD(vRot.x), DEG2RAD(vRot.y), DEG2RAD(vRot.z))), 
				false);
		}

		if (pColorTrack && pColorTrack->GetNumKeys() > 0)
		{
			Vec3 vColor(dl->m_Color.r, dl->m_Color.g, dl->m_Color.b);
			float duration = max(pColorTrack->GetKeyTime(pColorTrack->GetNumKeys()-1), 0.001f);
			float timeNormalized = static_cast<float>(fmod(time+phase*duration, duration));
			pColorTrack->GetValue(timeNormalized, vColor);
			dl->m_Color = ColorF(vColor.x/255.0f, vColor.y/255.0f, vColor.z/255.0f);
		}
		else
		{
			dl->m_Color = dl->m_BaseColor;
		}

		if (pDiffMultTrack && pDiffMultTrack->GetNumKeys() > 0)
		{
			float diffMult = 1.0;
			float duration = max(pDiffMultTrack->GetKeyTime(pDiffMultTrack->GetNumKeys()-1), 0.001f);
			float timeNormalized = static_cast<float>(fmod(time+phase*duration, duration));
			pDiffMultTrack->GetValue(timeNormalized, diffMult);
			dl->m_Color *= diffMult;
		}
		
		if (pRadiusTrack && pRadiusTrack->GetNumKeys() > 0)
		{
			float radius = dl->m_fRadius;
			float duration = max(pRadiusTrack->GetKeyTime(pRadiusTrack->GetNumKeys()-1), 0.001f);
			float timeNormalized = static_cast<float>(fmod(time+phase*duration, duration));
			pRadiusTrack->GetValue(timeNormalized, radius);
			dl->m_fRadius = radius;
		}

		if (pSpecMultTrack && pSpecMultTrack->GetNumKeys() > 0)
		{
			float specMult = dl->m_SpecMult;
			float duration = max(pSpecMultTrack->GetKeyTime(pSpecMultTrack->GetNumKeys()-1), 0.001f);
			float timeNormalized = static_cast<float>(fmod(time+phase*duration, duration));
			pSpecMultTrack->GetValue(timeNormalized, specMult);
			dl->m_SpecMult = specMult;
		}

		if (pHDRDynamicTrack && pHDRDynamicTrack->GetNumKeys() > 0)
  {
			float hdrDynamic = dl->m_fHDRDynamic;
			float duration = max(pHDRDynamicTrack->GetKeyTime(pHDRDynamicTrack->GetNumKeys()-1), 0.001f);
			float timeNormalized = static_cast<float>(fmod(time+phase*duration, duration));
			pHDRDynamicTrack->GetValue(timeNormalized, hdrDynamic);
			dl->m_fHDRDynamic = hdrDynamic;
		}
	}
  else if (nStyle>0 && nStyle<CLightStyle::m_LStyles.Num() && CLightStyle::m_LStyles[nStyle])
  {
    CLightStyle *ls = CLightStyle::m_LStyles[nStyle];

		const float fRecipMaxInt8 = 1.0f / 255.0f;

		// Add user light phase
		float fPhaseFromID = ((float)dl->m_nLightPhase) * fRecipMaxInt8;
		fTime += (fPhaseFromID - floorf(fPhaseFromID)) * ls->m_TimeIncr;

    ls->mfUpdate(fTime);

    dl->m_Color = dl->m_BaseColor * ls->m_Color;
		dl->m_SpecMult = dl->m_BaseSpecMult * ls->m_Color.a;
		dl->m_Origin = dl->m_BaseOrigin + ls->m_vPosOffset;
  }
	else
	{
		dl->m_Color = dl->m_BaseColor;
	}
	
	if( dl->m_AnimRotation[0] || dl->m_AnimRotation[1] || dl->m_AnimRotation[2] )
	{
		const float fInvMaxInt16 = 1.0f / 32768.0f;
		const float fConstTimeStep = 1.0f / 33.0f;
		Vec3 pAnimRotation = Vec3((float)dl->m_AnimRotation[0],(float)dl->m_AnimRotation[1], (float)dl->m_AnimRotation[2]);
		pAnimRotation *= fInvMaxInt16;
		
		fTime *= fConstTimeStep;
		Matrix33 pAnimRot = Matrix33::CreateRotationAA( pAnimRotation * fTime);
		dl->m_ObjMatrix.SetRotation33( Matrix33(dl->m_ObjMatrix) * Matrix33::CreateRotationAA( pAnimRotation* fTime) * pAnimRot );
		dl->m_ProjMatrix = dl->m_ProjMatrix * pAnimRot;
	}

	if(IsHDRModeEnabled())
	{
		I3DEngine *p3DEngine = (I3DEngine *)gEnv->p3DEngine;		assert(p3DEngine);

		float fHDR = powf( p3DEngine->GetHDRDynamicMultiplier(), dl->m_fHDRDynamic );
  	dl->m_Color *= fHDR;
	}  

  return false;
}

#if !defined(XENON) && !defined(PS3) && !defined(CAFE)
void CRenderer::FX_ApplyShaderQuality(EShaderType eST)
{
  SShaderProfile *pSP = &m_cEF.m_ShaderProfiles[eST];
  m_RP.m_FlagsShader_RT &= ~(g_HWSR_MaskBit[HWSR_QUALITY] | g_HWSR_MaskBit[HWSR_QUALITY1]);
  int nQuality = (int)pSP->GetShaderQuality();
  m_RP.m_nShaderQuality = nQuality;
  switch (nQuality)
  {
    case eSQ_Medium:
      m_RP.m_FlagsShader_RT |= g_HWSR_MaskBit[HWSR_QUALITY];
      break;
    case eSQ_High:
		m_RP.m_FlagsShader_RT |= g_HWSR_MaskBit[HWSR_QUALITY1];
	  break;  
    case eSQ_VeryHigh:
      m_RP.m_FlagsShader_RT |= (g_HWSR_MaskBit[HWSR_QUALITY]|g_HWSR_MaskBit[HWSR_QUALITY1]);
      break;
  }
}
#endif

EShaderQuality CRenderer::EF_GetShaderQuality(EShaderType eST)
{
  SShaderProfile *pSP = &m_cEF.m_ShaderProfiles[eST];
  int nQuality = (int)pSP->GetShaderQuality();

  switch (nQuality)
  {
    case eSQ_Low:
      return eSQ_Low;
    case eSQ_Medium:
      return eSQ_Medium;
    case eSQ_High:
		return eSQ_High;
    case eSQ_VeryHigh:
      return eSQ_VeryHigh;
  }

  return eSQ_Low;
}

ERenderQuality CRenderer::EF_GetRenderQuality() const
{
  return (ERenderQuality) m_RP.m_eQuality;
}

#ifdef WIN64
#pragma warning( push )							//AMD Port
#pragma warning( disable : 4312 )				// 'type cast' : conversion from 'int' to 'void *' of greater size
#endif
 
int CRenderer::RT_CurThreadList()
{
  return m_pRT->GetThreadList();
}

void *CRenderer::EF_Query(int Query, INT_PTR Param)
{
  static int nSize;

  switch (Query)
  {
    case EFQ_DeleteMemoryArrayPtr:
      {
        char *pPtr = (char *)Param;
        delete [] pPtr;
      }
      break;
    case EFQ_DeleteMemoryPtr:
      {
        char *pPtr = (char *)Param;
        delete pPtr;
      }
      break;
    case EFQ_GetShaderCombinations:
      {
        const char *szPtr = CHWShader::GetCurrentShaderCombinations(true);
        return (void *)szPtr;
      }
      break;
    case EFQ_SetShaderCombinations:
      {
        if (CV_r_shaderspreactivate)
        {
          iLog->Log("--- Preactivate shaders...");
          iLog->UpdateLoadingScreen(0);
          bool bRes = CHWShader::PreactivateShaders();
				  m_cEF.m_bActivated = true;
        }
        return NULL;
      }
      break;
    case EFQ_CloseShaderCombinations:
      {
        m_cEF.mfCloseShadersCache(0);
        return NULL;
      }
      break;
    case EFQ_LightSource:
      {
#       ifndef _RELEASE
        if (SRendItem::m_RecurseLevel[m_RP.m_nFillThreadID] == 0) __debugbreak();
#       endif
        if (m_RP.m_DLights[m_RP.m_nFillThreadID][SRendItem::m_RecurseLevel[m_RP.m_nFillThreadID]-1].Num() > (uint32)Param)
				{
					return (void*) &m_RP.m_DLights[m_RP.m_nFillThreadID][SRendItem::m_RecurseLevel[m_RP.m_nFillThreadID]-1][(int)Param];
				}
        return NULL;
      }
      break;

    case EFQ_MainThreadList:
      return (void *)m_RP.m_nFillThreadID;
    case EFQ_RenderThreadList:
      return (void *)m_RP.m_nProcessThreadID;
    case EFQ_RenderMultithreaded:
      nSize = m_pRT->IsMultithreaded();
      return (void *)nSize;
      break;

    case EFQ_Pointer2FrameID:
      return (void *)&m_RP.m_TI[m_pRT->GetThreadList()].m_nFrameID;
    case EFQ_DeviceLost:
      nSize = (int)m_bDeviceLost;
      return (void *)&nSize;
		case EFQ_D3DDevice:
			return gGet_D3DDevice();
    case EFQ_RecurseLevel:
      return (void *)(UINT_PTR)SRendItem::m_RecurseLevel[m_pRT->GetThreadList()];
    case EFQ_Alloc_APITextures:
      {
        nSize = 0;
        SResourceContainer *pRL = CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
        if (pRL)
        {
          ResourcesMapItor itor;
          for (itor=pRL->m_RMap.begin(); itor!=pRL->m_RMap.end(); itor++)
          {
            CTexture *tp = (CTexture *)itor->second;
            if (!tp || tp->IsNoTexture())
              continue;
#if !defined(XENON) && !defined(PS3) && !defined(CAFE)
            if (!(tp->GetFlags() & (FT_USAGE_DYNAMIC | FT_USAGE_RENDERTARGET)))
              nSize += tp->GetDeviceDataSize();


#endif
          }
        }
        return (void *)&nSize;
      }
      break;
		case EFQ_PS3_Resource_Stats:
			{
				void* pData	=	0;



        return pData;
			}
			break;
    case EFQ_Alloc_APIMesh:
#     if !defined(__SPU__)
			{
        nSize = 0;
        for (SIntrusiveList *iter = CRenderMesh::m_MeshList.next; iter != &CRenderMesh::m_MeshList; iter = iter->next)
				{
					CRenderMesh* pRM = iter->entry<CRenderMesh, &CRenderMesh::m_Chain>();
          nSize += pRM->Size(CRenderMesh::SIZE_VB);
					nSize += pRM->Size(CRenderMesh::SIZE_IB);
				}
        return (void *)&nSize;
      }
#     endif
      break;
		
		case EFQ_Alloc_Mesh_SysMem:
#     if !defined(__SPU__)
			{
				nSize = 0;
        for (SIntrusiveList *iter = CRenderMesh::m_MeshList.next; iter != &CRenderMesh::m_MeshList; iter = iter->next)
				{
					CRenderMesh* pRM = iter->entry<CRenderMesh, &CRenderMesh::m_Chain>();
					nSize += pRM->Size(CRenderMesh::SIZE_ONLY_SYSTEM);
				}
				return (void *)&nSize;
			}
#     endif
			break;
		
		case EFQ_Mesh_Count:
			{
				nSize = 0;
				AUTO_LOCK(CRenderMesh::m_sLinkLock);
        for (SIntrusiveList *iter = CRenderMesh::m_MeshList.next; iter != &CRenderMesh::m_MeshList; iter = iter->next)
				{
					nSize++;
				}
				return (void *)&nSize;
			}
			break;

		case EFQ_GetAllMeshes:
			{
				//Get render mesh lock, to ensure that the mesh list doesn't change while we're copying
				AUTO_LOCK(CRenderMesh::m_sLinkLock);
				IRenderMesh ***pppMeshes = (IRenderMesh***)Param;
				nSize = 0;
        for (SIntrusiveList *iter = CRenderMesh::m_MeshList.next; iter != &CRenderMesh::m_MeshList; iter = iter->next)
				{
					nSize++;
				}
				if (pppMeshes && nSize)
				{
#         if !defined(__SPU__)
					//allocate the array. The calling function is responsible for cleaning it up.
					*pppMeshes = new IRenderMesh*[nSize];
					nSize = 0;
	        for (SIntrusiveList *iter = CRenderMesh::m_MeshList.next; iter != &CRenderMesh::m_MeshList; iter = iter->next)
					{
						(*pppMeshes)[nSize] = iter->entry<CRenderMesh, &CRenderMesh::m_Chain>();;
						nSize++;
					}
#         endif
				}
				return (void *)&nSize;
			}
			break;

		case EFQ_GetAllTextures:
			{
				nSize = 0;
				ITexture **pTextures = (ITexture**)Param;
				SResourceContainer *pRL = CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
				if (pRL)
				{
					ResourcesMapItor itor;
					for (itor=pRL->m_RMap.begin(); itor!=pRL->m_RMap.end(); itor++)
					{
						CTexture *tp = (CTexture *)itor->second;
						if (!tp || tp->IsNoTexture())
							continue;
						if (pTextures)
						{
							pTextures[nSize] = tp;
						}
						nSize++;
					}
				}
				return (void *)&nSize;
			}
			break;
		case EFQ_TexturesPoolSize:
			nSize = (CRenderer::GetTexturesstreampoolsize() + 2) * 1024 * 1024;
			return (void *)&nSize;
			break;

		case EFQ_RenderTargetPoolSize:
			nSize = (CRenderer::CV_r_rendertargetpoolsize + 2) * 1024 * 1024;
			return (void *)&nSize;
			break;

		case EFQ_HDRModeEnabled:
			return IsHDRModeEnabled() ? (void *)1 : 0;

#ifndef _RELEASE
	  case EFQ_GetShadowPoolFrustumsNum:
			return ((uint32 *) &m_RP.m_PS[m_RP.m_nProcessThreadID].m_NumShadowPoolFrustums);
		case EFQ_GetShadowPoolAllocThisFrameNum:
			return ((uint32 *) &m_RP.m_PS[m_RP.m_nProcessThreadID].m_NumShadowPoolAllocsThisFrame);
#endif
	
		case EFQ_MultiGPUEnabled:
			return IsMultiGPUModeActive() ? (void *)1 : 0;

		case EFQ_sLinearSpaceShadingEnabled:
			return IsLinearSpaceShadingEnabled() ? (void *)1 : 0;		// sRGB

		case EFQ_DrawNearFov:
			{
				static float prevValue;
				prevValue = CV_r_drawnearfov;
				if (Param)
					CV_r_drawnearfov = *(float*) Param;
				return (void*) &prevValue;
			}

		case EFQ_TextureStreamingEnabled:
			return CRenderer::CV_r_texturesstreaming ? (void *)1 : 0;

		case EFQ_MSAAEnabled:
			return m_RP.IsMSAAEnabled() ? (void *)1 : 0;

		case EFQ_Fullscreen:
			return QueryIsFullscreen() ? (void *)1 : 0;

		case EFQ_GetTexStreamingInfo:
			{
				STextureStreamingStats* stats = (STextureStreamingStats*)Param;
				if(stats)
				{
					stats->nCurrentPoolSize = CTexture::s_nStatsCurManagedStreamedTexMem;
					stats->bPoolOverflow = CTexture::s_bPoolOverflow;
					stats->bPoolOverflowTotally = CTexture::s_bPoolOverflowTotally;
					CTexture::s_bPoolOverflowTotally = 0;
					stats->nStaticTexturesSize = CTexture::s_nStatsCurManagedNonStreamedTexMem;
					stats->nMaxPoolSize = CRenderer::GetTexturesstreampoolsize() * 1024 * 1024;
					stats->nThroughput =  (CTexture::s_nStreamingTotalTime > 0.f) ? uint32((float)CTexture::s_nStreamingThroughput / CTexture::s_nStreamingTotalTime) : 0;
#ifndef _RELEASE
					stats->nNumTexturesPerFrame = m_RP.m_PS[m_RP.m_nProcessThreadID].m_NumTextures;
#endif
					if(stats->bComputeReuquiredTexturesPerFrame)
					{
						stats->nRequiredTexturesSize = 0;
						// compute all sizes
						SResourceContainer *pRL = CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
						if (pRL)
						{
							ResourcesMapItor itor;
							for (itor=pRL->m_RMap.begin(); itor!=pRL->m_RMap.end(); itor++)
							{
								CTexture *tp = (CTexture *)itor->second;
								if (!tp || tp->IsNoTexture() || tp->IsUnloaded())
									continue;
								
								const int nCurMip = tp->GetRuquiredMip();
								stats->nRequiredTexturesSize += CTexture::TextureDataSize(max(1, tp->CTexture::GetWidth() >> nCurMip),
									max(1, tp->CTexture::GetHeight() >> nCurMip), tp->CTexture::GetDepth(), max(1, tp->GetNumMipsNonVirtual() - nCurMip), tp->GetDstFormat()) * tp->GetNumSides();
								stats->nRequiredTexturesCount++;
							}
						}
					}
				}
				return (void *)(CTexture::s_nStreamingTotalTime > 0.f && stats != NULL);
			}

		case EFQ_GetShaderCacheInfo:
			{
				SShaderCacheStatistics* pStats = (SShaderCacheStatistics*)Param;
				if (pStats)
				{
					memcpy(pStats, &m_cEF.m_ShaderCacheStats, sizeof(SShaderCacheStatistics));
					pStats->m_bShaderCompileActive = !CV_r_shadersnocompile;
				}
				return pStats;
			}

		case EFQ_HalfPixelShiftNeeded:
			{
			#if HALF_PIXEL_SHIFT_NEEDED
				return (void*)true;
			#else
				return 0;
			#endif
			}

		case EFQ_OverscanBorders:
			{
				return (void*) &s_overscanBorders;
			}
		
		case EFQ_NumActivePostEffects:
			{
				nSize = 0;
				if(CV_r_PostProcess && PostEffectMgr())
				{
					//assume query is from main thread
					nSize = PostEffectMgr()->GetActiveEffects(m_RP.m_nFillThreadID).size();
				}

				if( CV_r_SSAO )
				{
					nSize++;
				}

				return (void*)&nSize;		
			}

		case EFQ_GetFogCullDistance:
			{
				return &m_fogCullDistance;
			}

		case EFQ_GetMaxRenderObjectsNum:
			{
				nSize = MAX_REND_OBJECTS;
				return (void*)&nSize;
			}

		case EFQ_IsRenderLoadingThreadActive:
			{
				if(m_pRT && m_pRT->m_pThreadLoading)
				{
					return (void*)1;
				}
				return 0;
			}


    case EFQ_GetMeshPoolInfo:
    {
      if(SMeshPoolStatistics* stats = reinterpret_cast<SMeshPoolStatistics*>(Param))
	  {
        CRenderMesh::GetPoolStats(stats);
				return stats;
	  }
      return NULL; 
    }

	default:
      assert(0);
  }
  return NULL;
}

#ifdef WIN64
#pragma warning( pop )							//AMD Port
#endif

void CRenderer::ForceGC(){gRenDev->m_pRT->RC_ForceMeshGC(false);}

//================================================================================================================

IRenderMesh * CRenderer::CreateRenderMesh(const char *szType, const char *szSourceName,IRenderMesh::SInitParamerers *pInitParams )
{
	if (pInitParams)
	{
		return CreateRenderMeshInitialized(pInitParams->pVertBuffer,pInitParams->nVertexCount,pInitParams->eVertexFormat,pInitParams->pIndices,pInitParams->nIndexCount,pInitParams->nPrimetiveType,szType,szSourceName,
			pInitParams->eType,pInitParams->nRenderChunkCount,pInitParams->nClientTextureBindID,0,0,pInitParams->bOnlyVideoBuffer,pInitParams->bPrecache,pInitParams->pTangents, pInitParams->bLockForThreadAccess);
	}

	MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_RenderMeshType, 0, szType);
	MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_RenderMesh, 0, szSourceName);

  // make material table with clean elements
  CRenderMesh *pRenderMesh = new CRenderMesh(szType,szSourceName);
  pRenderMesh->AddRef();

  return pRenderMesh;
}

void CRenderer::DeleteRenderMesh(IRenderMesh * pLBuffer)
{
  if(pLBuffer)
	{
		pLBuffer->Release();
	}
}

// Creates the RenderMesh with the materials, secondary buffer (system buffer)
// indices and perhaps some other stuff initialized.
// NOTE: if the pVertBuffer is NULL, the system buffer doesn't get initialized with any values
// (trash may be in it)
IRenderMesh * CRenderer::CreateRenderMeshInitialized(
  void * pVertBuffer, int nVertCount, EVertexFormat eVF, 
  uint16 * pIndices, int nIndices,
  const PublicRenderPrimitiveType nPrimetiveType, const char *szType, const char *szSourceName, ERenderMeshType eBufType,
  int nMatInfoCount, int nClientTextureBindID,
  bool (*PrepareBufferCallback)(IRenderMesh *, bool),
  void *CustomData,bool bOnlyVideoBuffer, bool bPrecache, 
	SPipTangents * pTangents, bool bLockForThreadAcc)
{
	MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_RenderMeshType, 0, szType);
	MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_RenderMesh, 0, szSourceName);

  CRenderMesh * pRenderMesh = new CRenderMesh(szType,szSourceName, bLockForThreadAcc);
	pRenderMesh->AddRef();
  pRenderMesh->LockForThreadAccess();

  // make mats info list
  pRenderMesh->m_Chunks.PreAllocate(nMatInfoCount);

  pRenderMesh->_SetVertexFormat(eVF);
  pRenderMesh->_SetNumVerts(nVertCount);
  pRenderMesh->_SetNumInds(nIndices);

  // copy vert buffer
  if (pVertBuffer && !PrepareBufferCallback && !bOnlyVideoBuffer)
  {
    pRenderMesh->UpdateVertices(pVertBuffer, nVertCount, 0, VSF_GENERAL, 0u, false);
		if (pTangents)
      pRenderMesh->UpdateVertices(pTangents, nVertCount, 0, VSF_TANGENTS, 0u, false);
  }

	pRenderMesh->m_pCustomData = CustomData;
  if (pIndices)
    pRenderMesh->UpdateIndices(pIndices, nIndices, 0, 0u, false);
  pRenderMesh->_SetPrimitiveType(GetInternalPrimitiveType(nPrimetiveType));
  pRenderMesh->_SetRenderMeshType(eBufType);

  pRenderMesh->m_nClientTextureBindID = nClientTextureBindID;

  // Precache for static buffers
  if (CV_r_meshprecache && pRenderMesh->_GetNumVerts() && bPrecache && !m_bDeviceLost && m_pRT->IsRenderThread())
  {
    pRenderMesh->CheckUpdate(eVF, -1);
#ifndef NULL_RENDERER
    assert (pRenderMesh->_HasVBStream(VSF_GENERAL));
#endif
  }

	pRenderMesh->UnLockForThreadAccess();
  return pRenderMesh;
}

//=======================================================================

void CRenderer::SetWhiteTexture()
{
  m_pRT->RC_SetTexture(CTexture::s_ptexWhite->GetID(), 0);
}

int CRenderer::GetWhiteTextureId() const
{
	const int textureId = (CTexture::s_ptexWhite) ? CTexture::s_ptexWhite->GetID() : -1;
	return textureId;
}

void CRenderer::SetTexture(int tnum)
{
  m_pRT->RC_SetTexture(tnum, 0);
}

// used for sprite generation
void CRenderer::SetTextureAlphaChannelFromRGB(byte * pMemBuffer, int nTexSize)
{
#ifndef XENON
  // set alpha channel
  for(int y=0; y<nTexSize; y++)
    for(int x=0; x<nTexSize; x++)
    {
      int t = (x+nTexSize*y)*4;
      if( abs(pMemBuffer[t+0]-pMemBuffer[0+0])<2 && 
          abs(pMemBuffer[t+1]-pMemBuffer[0+1])<2 && 
          abs(pMemBuffer[t+2]-pMemBuffer[0+2])<2 )
        pMemBuffer[t+3] = 0;
      else
        pMemBuffer[t+3] = 255;

      // set border alpha to 0
      if( x==0 || y == 0 || x == nTexSize-1 || y == nTexSize-1 )
        pMemBuffer[t+3] = 0;
    }



















#endif
}

//=============================================================================
// Precaching
bool CRenderer::EF_PrecacheResource(IRenderMesh *_pPB, IMaterial * pMaterial, float fMipFactor, float fTimeToReady, int nFlags, int nUpdateId)
{
  int i;
  if (!CRenderer::CV_r_texturesstreaming)
    return true;

	CRenderMesh * pPB = (CRenderMesh *)_pPB;

  for (i=0; i<pPB->m_Chunks.Count(); i++)
  {
    CRenderChunk *pChunk = &pPB->m_Chunks[i];
		assert(!"do pre-cache with real materials");

		assert(0);

		//@TODO: Timur
		assert( pMaterial && "RenderMesh must have material" );
    SRenderShaderResources *pSR = (SRenderShaderResources *)pMaterial->GetShaderItem(pChunk->m_nMatID).m_pShaderResources;
    if (!pSR)
      continue;
    if (pSR->m_nFrameLoad != m_RP.m_TI[m_RP.m_nProcessThreadID].m_nFrameID)
    {
      pSR->m_nFrameLoad = m_RP.m_TI[m_RP.m_nProcessThreadID].m_nFrameID;
      pSR->m_fMinMipFactorLoad = 999999.0f;
    }
    else
      if (fMipFactor >= pSR->m_fMinMipFactorLoad)
      continue;
    pSR->m_fMinMipFactorLoad = fMipFactor;
    for (int j=0; j<=pSR->m_nLastTexture; j++)
    {
      if (!pSR->m_Textures[j])
        continue;
      CTexture *tp = pSR->m_Textures[j]->m_Sampler.m_pTex;
      if (!tp)
        continue;
      fMipFactor *= pSR->m_Textures[j]->GetTiling(0) * pSR->m_Textures[j]->GetTiling(1);

      m_pRT->RC_PrecacheResource(tp, fMipFactor, 0, nFlags, nUpdateId);
    }
  }
  return true;
}

bool CRenderer::EF_PrecacheResource(CDLight *pLS, float fMipFactor, float fTimeToReady, int Flags, int nUpdateId)
{
  FUNCTION_PROFILER_FAST( GetISystem(),PROFILE_RENDERER,g_bProfilerEnabled );

  if (!CRenderer::CV_r_texturesstreaming)
    return true;

  ITexture *pLightTexture = pLS->GetLightTexture();
  if (pLightTexture)
    m_pRT->RC_PrecacheResource(pLightTexture, fMipFactor, 0, Flags, nUpdateId);
  if (pLS->GetDiffuseCubemap())
    m_pRT->RC_PrecacheResource(pLS->GetDiffuseCubemap(), fMipFactor, 0, Flags, nUpdateId);
  if (pLS->GetSpecularCubemap())
    m_pRT->RC_PrecacheResource(pLS->GetSpecularCubemap(), fMipFactor, 0, Flags, nUpdateId);
  return true;
}

void CRenderer::PrecacheTexture(ITexture *pTP, float fMipFactor, float fTimeToReady, int Flags, int nUpdateId, int nCounter)
{
  if (!CRenderer::CV_r_texturesstreaming)
    return;

  assert(m_pRT->IsRenderThread());

  if (pTP)
		((CTexture*)pTP)->CTexture::PrecacheAsynchronously(fMipFactor, Flags, nUpdateId, nCounter);
}

bool CRenderer::EF_PrecacheResource(IShader *pSH, float fMipFactor, float fTimeToReady, int Flags)
{
  if (!CRenderer::CV_r_texturesstreaming)
    return true;

  return true;
}

#ifdef USE_NV_DXT_LIB

#include "../../../Tools/nvDXTLibrary/nvDXTLibrary.h"

extern  byte *sDDSData;

NV_ERROR_CODE ReadDTXnFile(void *buffer, size_t count, void * userData)
{
	cryMemcpy(buffer, sDDSData, count);
	sDDSData += count;

	return NV_OK;
}
#endif


void CRenderer::DXTCompress_FastOnCPU( byte * pInData, byte * pOutData, const int width, const int height, const bool isDXT5 )
{
  const size_t mipSize = ((width + 3) / 4) * ((height + 3) / 4) * (isDXT5 ? 16 : 8);

  int size;
  RTDXTCompression::CompressImageDXT(pInData, pOutData, width, height, size, isDXT5);
  if(mipSize != size)
  {
    assert(0);
	gEnv->pLog->LogError("CRenderer::CompressToDXT: Failed to compress texture to DXT: %dB allocated, %dB compressed", (int32)mipSize, size);
  }
}

bool CRenderer::DXTDecompress(byte *srcData,const size_t srcFileSize,byte *dstData,int nWidth,int nHeight,int nMips,ETEX_Format eSrcTF, bool bUseHW, int nDstBytesPerPix)
{
#ifdef USE_NV_DXT_LIB
  if (nDstBytesPerPix != 3 && nDstBytesPerPix != 4)
    return false;

	if (DDSFormats::IsNormalMap(eSrcTF))
	{
    assert(0);
		return false;
	}

  // NOTE: AMD64 port: implement
  if (!bUseHW)
  {
    CImageExtensionHelper::DDS_HEADER *ddsh;
    int blockSize = (eSrcTF == eTF_DXT1 || eSrcTF == eTF_CTX1) ? 8 : 16;
    int DXTSize = ((nWidth+3)/4)*((nHeight+3)/4)*blockSize;
    byte *dd = new byte [DXTSize + sizeof(CImageExtensionHelper::DDS_HEADER) + sizeof(DWORD)];

    DWORD dwMagic = MAKEFOURCC('D','D','S',' ');
    *(DWORD *)dd = dwMagic;
    ddsh = (CImageExtensionHelper::DDS_HEADER *)&dd[sizeof(DWORD)];
    memset(ddsh, 0, sizeof(CImageExtensionHelper::DDS_HEADER));
    cryMemcpy(&dd[sizeof(DWORD)+sizeof(CImageExtensionHelper::DDS_HEADER)], srcData, DXTSize);

    ddsh->dwSize = sizeof(CImageExtensionHelper::DDS_HEADER);
    ddsh->dwWidth = nWidth;
    ddsh->dwHeight = nHeight;
    ddsh->dwHeaderFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_LINEARSIZE;
    ddsh->dwPitchOrLinearSize = nWidth*nHeight*4/blockSize;
    if (eSrcTF == eTF_DXT1)
      ddsh->ddspf.dwFourCC = DDSFormats::DDSPF_DXT1.dwFourCC;
    else
    if (eSrcTF == eTF_DXT3)
      ddsh->ddspf.dwFourCC = DDSFormats::DDSPF_DXT3.dwFourCC;
    else
    if (eSrcTF == eTF_DXT5)
      ddsh->ddspf.dwFourCC = DDSFormats::DDSPF_DXT5.dwFourCC;
    ddsh->ddspf.dwSize = sizeof(ddsh->ddspf);
    ddsh->ddspf.dwFlags = DDS_FOURCC;
    ddsh->dwSurfaceFlags = DDS_SURFACE_FLAGS_TEXTURE;

    sDDSData = dd;
//    int planes;
//    int lTotalWidth;
//    int rowBytes;
//    int width;
//    int height;
//    int src_format;

		nvImageContainer imageData;
		int readMIPMapCount=1;

		imageData.rgbaMIPImage.resize(1);
		imageData.rgbaMIPImage[0].realloc(nWidth,nHeight);		// to alloc memory in our DLL

		if(nvDXTdecompress_Wrapped(imageData,PF_RGBA,readMIPMapCount,ReadDTXnFile,0)!=NV_OK)
		{
			delete []dd;
			return false;
		}

		RGBAImage &mip = imageData.rgbaMIPImage[0];

		byte *_data = (byte *)mip.pixels();

		if (imageData.nPlanes != nDstBytesPerPix)
    {
      int n = imageData.width * imageData.height;
      if (imageData.nPlanes == 4)
      {
        assert (nDstBytesPerPix == 3);
        byte *data1 = _data;
        byte *dd1 = dstData;

        for (int i=0; i<n; i++)
        {
          dd1[0] = data1[2];
          dd1[1] = data1[1];
          dd1[2] = data1[0];
          dd1   += 3;
          data1 += 4;
        }
      }
      else
      if (imageData.nPlanes == 3)
      {
        assert (nDstBytesPerPix == 4);
        byte *data1 = _data;
        byte *dd1 = dstData;

        for (int i=0; i<n; i++)
        {
          dd1[0] = data1[2];
          dd1[1] = data1[1];
          dd1[2] = data1[0];
          dd1[3] = 255;
          dd1   += 4;
          data1 += 3;
        }
      }
    }
    else
      cryMemcpy(dstData, _data, imageData.width*imageData.height*imageData.nPlanes);

		delete []dd;
    return true;
  }
  else
#endif
  {
    return false;
  }
}

#ifdef USE_NV_DXT_LIB

// wrapper used to remove DDS header from the NVDXT callback
static void *g_pNVDXT_UserData=0;
static MIPDXTcallback g_pNVDXT_Callback=0;
static size_t g_NVDXT_HeaderToRead = 4+sizeof(CImageExtensionHelper::DDS_HEADER);		// magic word+struct

static NV_ERROR_CODE NVIDIA_DXTWriteCallback(const void *buffer,size_t count, const MIPMapData * mipMapData, void * userData)
{
	assert(g_pNVDXT_UserData);
	assert(g_pNVDXT_Callback);

	uint8 *newbuffer=(uint8 *)buffer;
	size_t newcount=count;

	// ignore the first few bytes (dds header)
	if(newcount>g_NVDXT_HeaderToRead)
	{
		newbuffer+=g_NVDXT_HeaderToRead;
		newcount-=g_NVDXT_HeaderToRead;
		g_NVDXT_HeaderToRead=0;
	}
	else
	{
		g_NVDXT_HeaderToRead-=count;
		newbuffer+=count;
		newcount=0;
	}

	if(newcount)
		g_pNVDXT_Callback(newbuffer,newcount,userData);

	return NV_OK;
}

#endif

bool CRenderer::DXTCompress( byte *raw_data,int nWidth,int nHeight,ETEX_Format eTF, bool bUseHW, bool bGenMips,
	int nSrcBytesPerPix, const Vec3 vLumWeight, MIPDXTcallback callback)
{
#ifdef WIN32
	if(IsBadReadPtr(raw_data, nWidth*nHeight*nSrcBytesPerPix))
	{
		assert(0);
		iLog->Log("Warning: CRenderer::DXTCompress: invalid data passed to the function");
		return false;
	}
#endif

#if !defined(EXCLUDE_SQUISH_SDK)
  if(!bUseHW)
	if(CV_r_TextureCompressor==1)							// try squish
	if(bGenMips==false)				// todo: support mips
	{
		squish::SSquishOptions squishoptions;			assert(squishoptions.m_flags==0);
		if(vLumWeight.x>0)
		{
			squishoptions.m_Weights[0]=vLumWeight.x;
			squishoptions.m_Weights[1]=vLumWeight.y;
			squishoptions.m_Weights[2]=vLumWeight.z;
		}

		switch(eTF)
		{
			case eTF_DXT1:	squishoptions.m_flags = squish::kDxt1; break;
//			case eTF_DXT3:	squishoptions.m_flags = squish::kDxt3; break;		// not yet supported - would require proper alpha treatment
			case eTF_DXT5:	squishoptions.m_flags = squish::kDxt5; break;		// not very well tested yet
			default: assert(0);		// maybe squish would support the format
		}
		if(squishoptions.m_flags)
		{
			int size = squish::GetStorageRequirements(nWidth,nHeight,squishoptions.m_flags);

			uint8 *pOutMem = new uint8[size];

			if(pOutMem)
			{      
				//				uint32 nMips = CTexture::CalcNumMips(nWidth, nHeight);
				//				for(uint32 dwMip=0;dwMip<nMips;++dwMip)
				{
					//					if (!nWidth)
					//						nWidth = 1;
					//					if (!nHeight)
					//						nHeight = 1;

					//					int size = squish::GetStorageRequirements(nWidth,nHeight,squishformat);

					squish::CompressImageBGRX(raw_data,nWidth,nHeight,pOutMem,squishoptions);

//					MIPMapData MMData;
//					MMData.height	=	nHeight;
//					MMData.width	=	nWidth;
//					MMData.mipLevel	=	0;
//					(*callback)(pOutMem,size,&MMData,NULL);
					(*callback)(pOutMem,size,NULL);

						//					nWidth >>= 1;
						//					nHeight >>= 1;
				}

				delete [] pOutMem;
				return true;
			}

			return false;		// not enough memory
		}
	}
#endif // NULL_RENDERER

#ifdef USE_NV_DXT_LIB
	// NOTE: AMD64 port: implement
  if (!bUseHW)
  {
    nvCompressionOptions opt;

		if(vLumWeight.x>0)
		{
			opt.weight[0]=vLumWeight.x;
			opt.weight[1]=vLumWeight.y;
			opt.weight[2]=vLumWeight.z;
			opt.weightType=kUserDefinedWeighting;
		}

    switch(eTF)
    {
			case eTF_A4R4G4B4:
				opt.textureFormat = k4444;
				break;
			case eTF_A8R8G8B8:
        opt.textureFormat = k8888;
				break;
      case eTF_DXT1:
        opt.textureFormat = kDXT1;
    	  break;
      case eTF_DXT3:
        opt.textureFormat = kDXT3;
        break;
      case eTF_DXT5:
        opt.textureFormat = kDXT5;
        break;
			case eTF_A8:
				opt.textureFormat = kA8;
				break;
			case eTF_L8:
				opt.textureFormat = kL8;
				break;
      default:
        assert(0);
        return false;
    }
    opt.mipFilterType = kMipFilterQuadratic;
    if (bGenMips)
      opt.mipMapGeneration = kGenerateMipMaps;
    else
      opt.mipMapGeneration = kNoMipMaps;

		g_pNVDXT_UserData=0;							// not utilized yet
		g_pNVDXT_Callback=callback;
		g_NVDXT_HeaderToRead = 4+sizeof(CImageExtensionHelper::DDS_HEADER);		// magic word+struct

		nvDXTcompress_Wrapped(raw_data,nWidth,nHeight,nWidth*nSrcBytesPerPix,nvBGRA,&opt,NVIDIA_DXTWriteCallback);

		g_pNVDXT_UserData=0;
		g_pNVDXT_Callback=0;
		g_NVDXT_HeaderToRead=0;

  }
  else
  {
    int i;
    byte *nDst = raw_data;
    if (nSrcBytesPerPix >= 3)
    {
      nDst = new byte[nWidth*nHeight*4];
			bool bUseAlpha = nSrcBytesPerPix > 3;
      if(bUseAlpha)
      {
        assert(nSrcBytesPerPix == 4);
        memcpy(nDst, raw_data, nWidth*nHeight*4);
      }
      else
      {
        for (i=0; i<nWidth*nHeight; i++)
        {
          nDst[i*4+0] = raw_data[i*nSrcBytesPerPix+0];
          nDst[i*4+1] = raw_data[i*nSrcBytesPerPix+1];
          nDst[i*4+2] = raw_data[i*nSrcBytesPerPix+2];
          nDst[i*4+3] = 255;
        }
      }
    }
    int nMips = 1;
    if (bGenMips)
      nMips = CTexture::CalcNumMips(nWidth, nHeight);
    int DXTSize = 0;
    byte *data = CTexture::Convert(nDst, nWidth, nHeight, nMips, eTF_A8R8G8B8, eTF, nMips, DXTSize, true);
    if (callback)
    {
      int blockSize = (eTF == eTF_DXT1 || eTF == eTF_CTX1) ? 8 : 16;
      int nOffs = 0;
      int wdt = nWidth;
      int hgt = nHeight;
      for (i=0; i<nMips; i++)
      {
        if (!wdt)
          wdt = 1;
        if (!hgt)
          hgt = 1;
        int nSize = ((wdt+3)/4)*((hgt+3)/4)*blockSize;
        assert(nSize+nOffs <= DXTSize);
//				MIPMapData MMData;
//				MMData.mipLevel	=	i;
//				MMData.width	=	wdt;
//				MMData.height	=	hgt;
//        (*callback)(&data[nOffs], nSize, &MMData, NULL);
				(*callback)(&data[nOffs], nSize, NULL);
        nOffs += nSize;
        wdt >>= 1;
        hgt >>= 1;
      }
    }
    delete [] data;
    if (nDst != raw_data)
      delete [] nDst;
  }
#endif
  return true;
}

extern void LoadJPGBuff(unsigned char *fbuffer, unsigned char **pic, int *width, int *height );

void CRenderer::LoadJPGBuff(unsigned char *fbuffer, unsigned char **pic, int *width, int *height)
{
#if !defined (XENON) && !defined(PS3) && !defined(WIN64) &&!defined(WIN32) && !defined(LINUX) && !defined(gringo) && !defined(CAFE)
  ::LoadJPGBuff(fbuffer, pic, width, height);
#endif
}

bool CRenderer::WriteJPG(byte *dat, int wdt, int hgt, char *name, int src_bits_per_pixel, int nQuality )
{
#ifdef USE_JPEG_LIB
	return ::WriteJPG(dat, wdt, hgt, name, src_bits_per_pixel, nQuality);
#else
	return false;
#endif
}

//////////////////////////////////////////////////////////////////////////
// IShaderPublicParams implementation class.
//////////////////////////////////////////////////////////////////////////

struct CShaderPublicParams : public IShaderPublicParams
{
  CShaderPublicParams()
  {
    m_nRefCount = 0;
  }

  virtual void AddRef() { m_nRefCount++; };
  virtual void Release() { if (--m_nRefCount <=0) delete this; };

  VIRTUAL void SetParamCount( int nParam ) { m_shaderParams.resize(nParam); }
  VIRTUAL int  GetParamCount() const { return m_shaderParams.size(); };

  VIRTUAL SShaderParam& GetParam( int nIndex )
  {
    assert( nIndex >= 0 && nIndex < (int)m_shaderParams.size()  );
    return m_shaderParams[nIndex];
  }

  VIRTUAL const SShaderParam& GetParam( int nIndex ) const
  {
    assert( nIndex >= 0 && nIndex < (int)m_shaderParams.size()  );
    return m_shaderParams[nIndex];
  }

  VIRTUAL void SetParam( int nIndex,const SShaderParam &param )
  {
    assert( nIndex >= 0 && nIndex < (int)m_shaderParams.size()  );
    m_shaderParams[nIndex] = param;
  }

  VIRTUAL void AddParam( const SShaderParam &param )
  {
    // shouldn't add existing parameter ?
    m_shaderParams.push_back(param);
  }

  VIRTUAL void SetParam(const char *pszName, UParamVal &pParam, EParamType nType = eType_FLOAT)
  {  
    int32 i;

    for (i=0; i<m_shaderParams.size(); i++)
    {
      if (!stricmp(pszName, m_shaderParams[i].m_Name))
      {
        break;
      }
    }

    if (i == m_shaderParams.size())
    {
      SShaderParam pr;
      strncpy(pr.m_Name, pszName, 32);    
      pr.m_Type = nType;
      m_shaderParams.push_back(pr);
    }

    SShaderParam::SetParam(pszName, &m_shaderParams, pParam);  
  }  

  VIRTUAL void SetShaderParams( const DynArray<SShaderParam> &pParams)
  {
    m_shaderParams = pParams;
  }

  /*virtual void AssignToRenderParams( struct SRendParams &rParams )
  {
    if (!m_shaderParams.empty())
      rParams.pShaderParams = &m_shaderParams;
  }*/

  VIRTUAL DynArray<SShaderParam> *GetShaderParams()
  {
    if (m_shaderParams.empty())
    {
      return 0;
    }

    return &m_shaderParams;
  }

  VIRTUAL const DynArray<SShaderParam> *GetShaderParams() const
  {
    if (m_shaderParams.empty())
    {
      return 0;
    }

    return &m_shaderParams;
  }

private:
  int m_nRefCount;
  DynArray<SShaderParam> m_shaderParams;
};

//////////////////////////////////////////////////////////////////////////
IShaderPublicParams* CRenderer::CreateShaderPublicParams()
{
	return new CShaderPublicParams;
}

#ifndef EXCLUDE_SCALEFORM_SDK

//////////////////////////////////////////////////////////////////////////
void CRenderer::SF_ConfigMask(ESFMaskOp maskOp, unsigned int stencilRef)
{
	int stencilFunc(FSS_STENCFUNC_ALWAYS);
	int stencilPass(FSS_STENCOP_KEEP);

	switch (maskOp)
	{
	case BeginSubmitMask_Clear:
		{
			stencilFunc = FSS_STENCFUNC_ALWAYS;
			stencilPass = FSS_STENCOP_REPLACE;
			break;
		}
	case BeginSubmitMask_Inc:
		{
			stencilFunc = FSS_STENCFUNC_EQUAL;
			stencilPass = FSS_STENCOP_INCR;
			break;
		}
	case BeginSubmitMask_Dec:
		{
			stencilFunc = FSS_STENCFUNC_EQUAL;
			stencilPass = FSS_STENCOP_DECR;
			break;
		}
	case EndSubmitMask:
		{
			stencilFunc = FSS_STENCFUNC_EQUAL;
			stencilPass = FSS_STENCOP_KEEP;
			break;
		}
	case DisableMask:
		{
			stencilFunc = FSS_STENCFUNC_ALWAYS;
			stencilPass = FSS_STENCOP_KEEP;
			break;
		}
	}

	FX_SetStencilState(STENC_FUNC(stencilFunc) | STENCOP_FAIL(FSS_STENCOP_KEEP) | 
		STENCOP_ZFAIL(FSS_STENCOP_KEEP) | STENCOP_PASS(stencilPass), stencilRef, 0xFFFFFFFF, 0xFFFFFFFF);
}

//////////////////////////////////////////////////////////////////////////
int CRenderer::SF_CreateTexture(int width, int height, int numMips, unsigned char* pData, ETEX_Format eTF, int flags)
{
	char name[128];
	sprintf(name, "$SF_%d", m_TexGenID++);

	flags |= !numMips ? FT_FORCE_MIPS : 0;

	CTexture* pTexture(CTexture::Create2DTexture(name, width, height, numMips, flags, pData, eTF, eTF));
	return (pTexture != 0) ? pTexture->GetID() : -1;
}

//////////////////////////////////////////////////////////////////////////
void CRenderer::SF_GetMeshMaxSize(int& numVertices, int& numIndices) const
{
	numVertices = m_RP.m_MaxVerts;
	numIndices = m_RP.m_MaxTris * 3;
}
#endif // #ifndef EXCLUDE_SCALEFORM_SDK

//////////////////////////////////////////////////////////////////////////
void CRenderer::GetThreadIDs(uint32& mainThreadID, uint32& renderThreadID) const
{
	if (m_pRT)
	{
		mainThreadID = m_pRT->m_nMainThread;
		renderThreadID = m_pRT->m_nRenderThread;
	}
	else
	{
		mainThreadID = renderThreadID = gEnv->mMainThreadId;
	}
}

void CRenderer::PostLevelLoading()
{
	int nThreadID = m_pRT->GetThreadList();
	m_RP.m_fogVolumeContibutions[nThreadID].reserve( 2048 );
}

//////////////////////////////////////////////////////////////////////////
uint16 CRenderer::PushFogVolumeContribution( const ColorF& fogVolumeContrib )
{
  int nThreadID = m_pRT->GetThreadList();

	const size_t maxElems( ( 1 << ( sizeof( uint16 ) * 8 ) ) - 1 );
	size_t numElems( m_RP.m_fogVolumeContibutions[nThreadID].size() );
	assert( numElems < maxElems);
	if( numElems >= maxElems )
		return (uint16) -1;

	m_RP.m_fogVolumeContibutions[nThreadID].push_back( fogVolumeContrib );
	return (uint16) ( m_RP.m_fogVolumeContibutions[nThreadID].size() - 1 );
}

//////////////////////////////////////////////////////////////////////////
void CRenderer::GetFogVolumeContribution( uint16 idx, ColorF &rColor ) const
{
	
	//assert( idx < m_RP.m_fogVolumeContibutions[m_RP.m_nProcessThreadID].size() );
	if( idx >= m_RP.m_fogVolumeContibutions[m_RP.m_nProcessThreadID].size() )
	{		
		rColor = ColorF( 0.0f, 0.0f, 0.0f, 1.0f );		
	}
	else
	{
		rColor = m_RP.m_fogVolumeContibutions[m_RP.m_nProcessThreadID][idx];
	}
}


const char * CRenderer::GetTextureFormatName(ETEX_Format eTF)
{
	return CTexture::NameForTextureFormat(eTF);
}

int CRenderer::GetTextureFormatDataSize(int nWidth, int nHeight, int nDepth, int nMips, ETEX_Format eTF)
{
	return CTexture::TextureDataSize(nWidth, nHeight, nDepth, nMips, eTF);
}


//////////////////////////////////////////////////////////////////////////
ERenderType CRenderer::GetRenderType() const
{
#if defined(DIRECT3D10)



		return eRT_DX11;

#elif defined(DIRECT3D9)



		return eRT_DX9;

#elif defined(NULL_RENDERER)
	return eRT_Null;
#else
	return eRT_Undefined;
#endif
}
static bool GetDDSImageHeader(const char* filename,CImageExtensionHelper::DDS_HEADER* output)
{
  FILE* pRawFile = gEnv->pCryPak->FOpen(filename,"rb");
  if( !pRawFile )
    return false;
  gEnv->pCryPak->FSeek (pRawFile, sizeof(DWORD), SEEK_SET);
  gEnv->pCryPak->FReadRaw (output, 1, sizeof(CImageExtensionHelper::DDS_HEADER), pRawFile);
  gEnv->pCryPak->FClose (pRawFile);
  return true;
}

bool CRenderer::GetImageCaps(const char* filename,int& width,int& height) const
{
  string fileExt = PathUtil::GetExt(filename);
  if( stricmp(fileExt.c_str(),"dds")==0 )
  {
    CImageExtensionHelper::DDS_HEADER header;
    if( GetDDSImageHeader(filename,&header) )
    {
      width = header.dwWidth;
      height = header.dwHeight;
      return true;
    }
    else
    {
      return false;
    }
  }
  _smart_ptr<CImageFile> pImage = CImageFile::mfLoad_file(filename,FIM_ALPHA);
  width = pImage->mfGet_width();
  height = pImage->mfGet_height();
  return pImage != NULL;
}

static int getBlockSize(const CImageExtensionHelper::DDS_PIXELFORMAT& format)
{
  if( format.dwFourCC==DDSFormats::DDSPF_DXT1.dwFourCC )
  {
    return (64/8);
  }
  else if( format.dwFourCC==DDSFormats::DDSPF_DXT5.dwFourCC )
  {
    return (64/8+64/8);
  }
  else if( format.dwFourCC==DDSFormats::DDSPF_3DC.dwFourCC )
  {
    return (128/8);
  }
  return 0;
}

inline int AlignTo4Nearest(float value)
{
  int iv = (int)value/4;
  int iv_div = (int)value%4;
  if( iv_div>2 )
  {
    iv=iv*4+4;
  }
  else
  {
    iv=iv*4;
  }
  return iv;
}

inline int AlignTo4Right(float value)
{
  //return AlignTo4Nearest(value);
  int iv = (int)(value/4.0f);
  iv*=4;
  if( value>0 )
  {
    float mod = fmod(value,4.0f);
    if( mod>0.0f )
      iv+=4;
    return iv;
  }
  return iv;
}

inline int AlignTo4Left(float value)
{
  //return AlignTo4Nearest(value);
  int iv = (int)(value/4.0f);
  iv*=4;
  if( value<0 )
  {
    float mod = fmod(value,4.0f);
    if( mod>0.0f )
      iv-=4;
    return iv;
  }
  return iv;
}

struct DDSProcessor
{
	bool loadData(const char* filename,CImageExtensionHelper::DDS_PIXELFORMAT& ioutputFormat) 
  {
    //
    outputFormat = ioutputFormat;
    //
    FILE* pRawFile = gEnv->pCryPak->FOpen(filename,"rb");
    if( !pRawFile )
      return false;
    gEnv->pCryPak->FSeek (pRawFile, 0, SEEK_END);
    long nFileSize = gEnv->pCryPak->FTell(pRawFile);
    gEnv->pCryPak->FSeek (pRawFile, 0, SEEK_SET);
    //
    m_fullbuffer.resize(nFileSize);
    //
    gEnv->pCryPak->FReadRaw (&m_fullbuffer[0], 1, nFileSize, pRawFile);
    gEnv->pCryPak->FClose (pRawFile);
    //
    //
    CImageExtensionHelper::DDS_HEADER* pDesc = (CImageExtensionHelper::DDS_HEADER*)(&m_fullbuffer[0]+sizeof(DWORD));
    input_Desc = *pDesc;
    m_srcData = (&m_fullbuffer[0]+sizeof(DWORD)+sizeof(CImageExtensionHelper::DDS_HEADER));
    //
    isDX1toDX1 = false;
    isDX1toDX5 = false;
    isDX5toDX5 = false;
    is3DCto3DC = false;
    //
    int srcBlockSize = getBlockSize(pDesc->ddspf);
    if( outputFormat.dwFourCC==DDSFormats::DDSPF_DXT1.dwFourCC && pDesc->ddspf.dwFourCC==DDSFormats::DDSPF_DXT1.dwFourCC ) 
    {
      isDX1toDX1 = true;
    }
    else if( outputFormat.dwFourCC==DDSFormats::DDSPF_DXT5.dwFourCC && pDesc->ddspf.dwFourCC==DDSFormats::DDSPF_DXT1.dwFourCC )
    {
      isDX1toDX5 = true;
    }
    else if( outputFormat.dwFourCC==DDSFormats::DDSPF_DXT5.dwFourCC && pDesc->ddspf.dwFourCC==DDSFormats::DDSPF_DXT5.dwFourCC )
    {
      isDX5toDX5 = true;
    }
    else if( outputFormat.dwFourCC==DDSFormats::DDSPF_3DC.dwFourCC && pDesc->ddspf.dwFourCC==DDSFormats::DDSPF_3DC.dwFourCC )
    {
      is3DCto3DC = true;
    }
    //
    return true;
  }
  //
  unsigned char* getMipData(byte* data,int dstMip,int fullW,int fullH,CImageExtensionHelper::DDS_PIXELFORMAT pixFormat);
  int getPitch(int dstMip,int fullW,int fullH,CImageExtensionHelper::DDS_PIXELFORMAT pixFormat);
  int getSrcMip(int dst_w,int dst_h,int src_w,int src_h,int src_w_mip0,int src_h_mip0);
  void BlitMipBlock(int dstMip,int dstTexWidth,int dstTexHeight,int dest_offsetx,int dest_offsety,int dest_x2,int dest_y2,int src_offsetx,int src_offsety,int src_x2,int src_y2,int src_w_mip0,int src_h_mip0,byte* pOutBuffer);
  //
  byte* m_srcData;
  std::vector<byte> m_fullbuffer;
  bool isDX1toDX1;
  bool isDX1toDX5;
  bool isDX5toDX5;
  bool is3DCto3DC;
  CImageExtensionHelper::DDS_HEADER input_Desc;
  CImageExtensionHelper::DDS_PIXELFORMAT outputFormat;
};


inline int Clamp(int val,int min_val,int max_val)
{
  if( val<min_val )
    return min_val;
  else if( val>max_val )
    return max_val;
  return val;
}

unsigned char* DDSProcessor::getMipData(byte* data,int dstMip,int fullW,int fullH,CImageExtensionHelper::DDS_PIXELFORMAT pixFormat)
{
  int o_width = fullW;
  int o_height = fullH;
  //
  int outBlockSize = getBlockSize(pixFormat);
  for(int n=0;n<dstMip;n++)
  {
    if( o_width<4 )
    {
      o_width = 4;
    }
    if( o_height<4 )
    {
      o_height = 4;
    }
    //
    int dstPitch4x4 = outBlockSize*o_width/4;
    data += dstPitch4x4*(o_height/4);
    //
    o_width >>=1;
    o_height >>=1;
    //
  }
  return data;
}

int DDSProcessor::getPitch(int dstMip,int fullW,int fullH,CImageExtensionHelper::DDS_PIXELFORMAT pixFormat)
{
  int o_width = fullW;
  int o_height = fullH;
  //
  int outBlockSize = getBlockSize(pixFormat);
  int dstPitch4x4 = outBlockSize*o_width/4;
  for(int n=0;n<dstMip;n++)
  {
    //
    o_width >>=1;
    o_height >>=1;
    //
    if( o_width<4 )
    {
      o_width = 4;
    }
    if( o_height<4 )
    {
      o_height = 4;
    }
    //
    dstPitch4x4 = outBlockSize*o_width/4;
  }
  return dstPitch4x4;
}

int DDSProcessor::getSrcMip(int dst_w,int dst_h,int src_w,int src_h,int src_w_mip0,int src_h_mip0)
{
  // 1 find 
  for(int n=0;!(src_w_mip0<4 && src_h_mip0<4);n++)
  {
    if( src_w_mip0<4 )
    {
      src_w_mip0 = 4;
    }
    if( src_h_mip0<4 )
    {
      src_h_mip0 = 4;
    }
    //
    if( src_w_mip0<=dst_w && src_h_mip0<=dst_h )
    {
      return n;
    }
    //
    src_w_mip0 >>=1;
    src_h_mip0 >>=1;
  }
  return 0;
}

void copyDXT5Transparency(byte* destBlockData,byte* srcBlockData,int destX,int destY,int srcX,int srcY )
{
  memcpy(destBlockData,srcBlockData,16/8);
  // transparency block 4x4 by 3bpp 
  uint64 alphaBlockData = *((uint64*)srcBlockData);
  alphaBlockData = alphaBlockData & 0xffffffffffff0000LL;
  int shiftBitCount = ((srcY)*4*3+srcX*3)+16;
  byte alphaVal = (byte)(alphaBlockData>>shiftBitCount);
  alphaVal = alphaVal & 0x7;
  int dstshiftBitCount = ((destY)*4*3+(destX)*3)+16;
  uint64 alphaBlockRes = ((uint64)alphaVal)<<dstshiftBitCount;
  *((uint64*)destBlockData)|=alphaBlockRes;
}


void DDSProcessor::BlitMipBlock(int dstMip,int dstTexWidth,int dstTexHeight,int dest_offsetx,int dest_offsety,int dest_x2,int dest_y2,int src_offsetx,int src_offsety,int src_x2,int src_y2,int src_w_mip0,int src_h_mip0,byte* pOutBuffer)
{
  int dst_w = dest_x2-dest_offsetx;
  int dst_h = dest_y2-dest_offsety;
  int src_w = src_x2-src_offsetx;
  int src_h = src_y2-src_offsety;
  // find src mip level
  byte* pDstMipData = getMipData(pOutBuffer,dstMip,dstTexWidth,dstTexHeight,outputFormat);
  int srcMip = getSrcMip(dst_w,dst_h,src_w,src_h,src_w_mip0,src_h_mip0);
  byte* pSrcMipData = getMipData(m_srcData,srcMip,input_Desc.dwWidth,input_Desc.dwHeight,input_Desc.ddspf);
  //
  int srcPitch4x4 = getPitch(srcMip,input_Desc.dwWidth,input_Desc.dwHeight,input_Desc.ddspf);
  int srcBlockSize = getBlockSize(input_Desc.ddspf);
  //
  int dstPitch4x4 = getPitch(dstMip,dstTexWidth,dstTexHeight,outputFormat);
  int dstBlockSize = getBlockSize(outputFormat);
  //
  if( dst_w<src_w )
  {
    int factor = src_w/dst_w;
    src_w = min(dst_w,src_w);
    src_offsetx = src_offsetx/factor;
  }
  if( dst_h<src_h )
  {
    int factor = src_h/dst_h;
    src_h = min(dst_h,src_h);
    src_offsety = src_offsetx/factor;
  }
  int resizeFactorX =  dst_w/src_w;
  int resizeFactorY =  dst_h/src_h;
  //
  // to match
  bool bResize = false;
  if( resizeFactorX!=1 || resizeFactorY!=1 )
  {
    bResize = true;
  }
  //
  if( !bResize )
  {
    int y_src=src_offsety;
    for(int y_dst=dest_offsety;y_dst<dest_y2;y_dst+=4,y_src+=4)
    {
      int x_src=src_offsetx;
      for(int x_dst=dest_offsetx;x_dst<dest_x2;x_dst+=4,x_src+=4)
      {
        byte* srcBlockDataLine = pSrcMipData+(y_src/4)*srcPitch4x4;
        byte* dstBlockDataLine = pDstMipData+(y_dst/4)*dstPitch4x4;
        // error if xCur and yCur is not bound 4x4 block
        if( isDX1toDX1 || isDX5toDX5 || is3DCto3DC )
        {
          // full line in one pass
          byte* srcBlockData = srcBlockDataLine+(x_src/4)*srcBlockSize;
          byte* dstBlockData = dstBlockDataLine+(x_dst/4)*dstBlockSize;
          memcpy(dstBlockData,srcBlockData,src_w/4*srcBlockSize);
          break;
        }
        else if( isDX1toDX5 )
        {
          byte* srcBlockData = srcBlockDataLine+(x_src/4)*srcBlockSize;
          byte* dstBlockData = dstBlockDataLine+(x_dst/4)*dstBlockSize;
          // no transparency
          // copy color block
          memcpy(dstBlockData+64/8,srcBlockData,srcBlockSize);
          // fill 1 alphas
          memset(dstBlockData,0xffffff,64/8);
        }
        else
        {
          assert(0);
        }
      }
    }
  }
  else
  {
    std::vector<byte> srcBlock; 
    //
    srcBlock.resize(srcBlockSize);
    //
    int exremeDataSize = (8*4)/8;
    int exremeDataOffset = (6*4*4)/8;
    int colorDataOffset = 0;
    //
    for(int y_dst=dest_offsety;y_dst<dest_y2;y_dst+=4)
    {
      for(int x_dst=dest_offsetx;x_dst<dest_x2;x_dst+=4)
      {
        // clear block
        memset(&srcBlock[0],0,srcBlock.size());
        //
        int curDstXDelta = x_dst-dest_offsetx;
        int curDstYDelta = y_dst-dest_offsety;
        int x_src=(src_offsetx+curDstXDelta)/resizeFactorX;
        int y_src=(src_offsety+curDstYDelta)/resizeFactorY;
        int x_src_div_block=(src_offsetx+curDstXDelta)%resizeFactorX;
        int y_src_div_block=(src_offsety+curDstYDelta)%resizeFactorY;
        //
        byte* srcBlockDataLine = pSrcMipData+(y_src/4)*srcPitch4x4;
        byte* dstBlockDataLine = pDstMipData+(y_dst/4)*dstPitch4x4;
        //
        byte* dstBlockData = dstBlockDataLine+(x_dst/4)*dstBlockSize;
        byte* srcBlockData = srcBlockDataLine+(x_src/4)*srcBlockSize;
        // copy extreme data
        if( input_Desc.ddspf.dwFourCC==DDSFormats::DDSPF_DXT1.dwFourCC )
        {
          memcpy(&srcBlock[0],srcBlockData,(16+16)/8);
        }
        else if( input_Desc.ddspf.dwFourCC==DDSFormats::DDSPF_DXT5.dwFourCC )
        {
          // color extr
          memcpy(&srcBlock[0]+64/8,srcBlockData+64/8,(16+16)/8);
        }
        else if( input_Desc.ddspf.dwFourCC==DDSFormats::DDSPF_3DC.dwFourCC )
        {
        }
        // copy color/alpha data
        for(int by=0;by<4;by++)
        {
          for(int bx=0;bx<4;bx++)
          {
            int x_src_block=(src_offsetx+curDstXDelta+bx)/resizeFactorX;
            int y_src_block=(src_offsety+curDstYDelta+by)/resizeFactorY;
            int x_src_div=x_src_block%4;
            int y_src_div=y_src_block%4;
            if( input_Desc.ddspf.dwFourCC==DDSFormats::DDSPF_DXT1.dwFourCC )
            {
              // one row is 1 byte 
              byte srcColor = srcBlockData[(16+16)/8+y_src_div*8/8];
              srcColor = ((0x3<<((x_src_div)*2)) & srcColor)>>((x_src_div)*2);
              srcBlock[by+(16+16)/8] |= srcColor<<((bx)*2);
            }
            else if( input_Desc.ddspf.dwFourCC==DDSFormats::DDSPF_DXT5.dwFourCC )
            {
              // one row is 1 byte 
              byte srcColor = srcBlockData[(16+16)/8+y_src_div*8/8+64/8];
              srcColor = ((0x3<<((x_src_div)*2)) & srcColor)>>((x_src_div)*2);
              srcBlock[by+(16+16)/8+64/8] |= srcColor<<((bx)*2);
              // transparency block 
              copyDXT5Transparency(&srcBlock[0],srcBlockData,bx,by,x_src_div,y_src_div);
            }
            else if( input_Desc.ddspf.dwFourCC==DDSFormats::DDSPF_3DC.dwFourCC )
            {
              copyDXT5Transparency(&srcBlock[0],srcBlockData,bx,by,x_src_div,y_src_div);
              copyDXT5Transparency(&srcBlock[0]+(8+8+3*16)/8,srcBlockData+(8+8+3*16)/8,bx,by,x_src_div,y_src_div);
            }
          }
        }
        srcBlockData = &srcBlock[0];
        // error if xCur and yCur is not bound 4x4 block
        if( isDX1toDX1 || isDX5toDX5 || is3DCto3DC )
        {
          // 
          memcpy(dstBlockData,srcBlockData,srcBlockSize);
        }
        else if( isDX1toDX5 )
        {
          // no transparency
          // copy color block
          memcpy(dstBlockData+64/8,srcBlockData,srcBlockSize);
          // fill 1 alphas
          memset(dstBlockData,0xffffff,64/8);
        }
        else
        {
          assert(0);
        }
      }
    }
  }
}

bool CRenderer::MergeImages(const char* output_filename,int out_width,int out_height,const char** files,int* offsetsX,int* offsetsY,int* widths,int* heights,int* src_offsetsX,int* src_offsetsY,int* src_width,int* src_height, int count) const
{
  //SaveTga()
  //
  int numOutMips = 0;
  CImageExtensionHelper::DDS_PIXELFORMAT outputFormat;
  for(int n=0;n<count;n++)
  {
    if( offsetsX[n]%4!=0 )
    {
      CryLog( "texture %s x offset %d in atlas is not divisible by 4",files[n],offsetsX[n]);
      return false;
    }
    if( offsetsY[n]%4!=0 )
    {
      CryLog( "texture %s y offset %d in atlas is not divisible by 4",files[n],offsetsY[n]);
      return false;
    }
    if( src_offsetsX[n]%4!=0 )
    {
      CryLog( "src texture %s x offset %d in atlas is not divisible by 4",files[n],offsetsX[n]);
      return false;
    }
    if( src_offsetsY[n]%4!=0 )
    {
      CryLog( "src texture %s y offset %d in atlas is not divisible by 4",files[n],offsetsY[n]);
      return false;
    }
    if( widths[n]%4!=0 )
    {
      CryLog( "texture %s width %d in atlas is not divisible by 4",files[n],widths[n]);
      return false;
    }
    if( heights[n]%4!=0 )
    {
      CryLog( "texture %s height %d in atlas is not divisible by 4",files[n],heights[n]);
      return false;
    }

    CImageExtensionHelper::DDS_HEADER header;
    GetDDSImageHeader(files[n],&header);
    if( n==0)
    {
      outputFormat = header.ddspf;
    }
    if( header.ddspf.dwFourCC==DDSFormats::DDSPF_DXT1.dwFourCC )
    {
      if( outputFormat.dwFourCC == DDSFormats::DDSPF_DXT5.dwFourCC )
      {
        CryLog("texmap %s is dxt1 in series of dxt5 textures",files[n]);
      }
      if( outputFormat.dwFourCC == DDSFormats::DDSPF_DXT1.dwFourCC )
      {
        // dxt5 overrides dxtc1
        outputFormat = DDSFormats::DDSPF_DXT1;
      }
    }
    else if( header.ddspf.dwFourCC==DDSFormats::DDSPF_DXT5.dwFourCC )
    {
      if( outputFormat.dwFourCC == DDSFormats::DDSPF_DXT1.dwFourCC )
      {
        CryLog("texmap %s is dxt5 in series of dxt1 textures",files[n]);
      }
      outputFormat = DDSFormats::DDSPF_DXT5;
    }
    else if( header.ddspf.dwFourCC==DDSFormats::DDSPF_3DC.dwFourCC )
    {
      if( outputFormat.dwFourCC!=DDSFormats::DDSPF_3DC.dwFourCC )
      {
        CryLog( "texture %s in not in 3dc in series of 3dc textures",files[n]);
        // all should be in 3dc
        return false;
      }
      outputFormat = DDSFormats::DDSPF_3DC;
    }
    else
    {
      CryLog( "unsupported to merge textures with formats %04X and %04X. Texture:%s",header.ddspf.dwFourCC,outputFormat.dwFourCC,files[n]);
      // unsupported
      return false;
    }
    //    int OutMips = max(header.dwMipMapCount,numOutMips);
    //  int clampedOutMips = (32-NumLeadingZeros())-2;
    numOutMips = max((int)header.dwMipMapCount,numOutMips);
  }
  //
  /*
  int w = out_width;
  int h = out_height;
  numOutMips = 1;
  while(!(w==1 && h==1))
  {
    w>>=1;
    h>>=1;
    if( w==0 )
      w = 1;
    if( h==0 )
      h = 1;
    //
    numOutMips++;
  }
  //
  numOutMips = 2;
  */
  //
  //numOutMips = 1;
  //
  int numPixelsTotal = 0;
  int w = out_width;
  int h = out_height;
  for(int m=0;m<numOutMips;m++)
  {
    if( w<4 )
    {
      w = 4;
    }
    if( h<4 )
    {
      h = 4;
    }
    numPixelsTotal+=w*h;
    //
    w>>=1;
    h>>=1;
  }
  //
  int outBlockSize = 0;
  outBlockSize = getBlockSize(outputFormat);
  // 64 bits for 4x4 block - DXT1
  // 64 bits color and 64 bits alpha 4x4 block DXT5
  // 128 bits for 4x4 block 3DC
  std::vector<byte> data(numPixelsTotal/16*outBlockSize,0);
  DDSProcessor processor;
  //
  std::set<string> uniq_files;
  for(int n=0;n<count;n++)
  {
    uniq_files.insert(files[n]);
  }
  //
  for( std::set<string>::iterator it = uniq_files.begin();it!=uniq_files.end();++it)
  {
    processor.loadData(*it,outputFormat);
    //
    for(int n=0;n<count;n++)
    {
      // dispatch only *it src texture
      if( strcmp(files[n],*it)!=0 )
        continue;
      //
      // ignore duplicates
      bool isDuplicate = false;
      /*
      for(int n1=0;n1<n;n1++)
      {
      if( strcmp(files[n1],files[n])==0 )
      {
      isDuplicate = true;
      break;
      }
      }
      if( isDuplicate )
      {
      continue;
      }
      */
      //
      //
      // till 4x4 block
      int i_rect_width = src_width[n];
      int i_rect_height = src_height[n];
      int i_offsetX = src_offsetsX[n];
      int i_offsetY = src_offsetsY[n];
      int i_fullWidth = processor.input_Desc.dwWidth;
      int i_fullHeight = processor.input_Desc.dwHeight;
      //
      byte* curOMipData = &data[0];
      byte* endOutData = &data[data.size()];
      int o_rect_width = widths[n];
      int o_rect_height = heights[n];
      int o_offsetx = offsetsX[n];
      int o_offsety = offsetsY[n];
      int o_fullWidth = out_width;
      int o_fullHeight = out_height;
      //numOutMips = 2;
      byte* last4x4Block = 0;
      for(int m=0;m<numOutMips;m++)
      {
        if( o_fullWidth<4 )
        {
          o_fullWidth = 4;
        }
        if( o_fullHeight<4 )
        {
          o_fullHeight = 4;
        }
        if( i_fullWidth<4 )
        {
          i_fullWidth = 4;
        }
        if( i_fullHeight<4 )
        {
          i_fullHeight = 4;
        }
        // in any case by 4x4 block
        // DEST calc offset block
        int dest_offsetx = Clamp(AlignTo4Left((float)o_offsetx),0,o_fullWidth);
        int dest_offsety = Clamp(AlignTo4Left((float)o_offsety),0,o_fullHeight);
        int dest_x2 = Clamp(AlignTo4Right((float)(o_offsetx+o_rect_width)),0,o_fullWidth);
        int dest_y2 = Clamp(AlignTo4Right((float)(o_offsety+o_rect_height)),0,o_fullHeight);
        // SRC calc offset block
        int src_offsetx = Clamp(AlignTo4Left((float)i_offsetX),0,i_fullWidth);
        int src_offsety = Clamp(AlignTo4Left((float)i_offsetY),0,i_fullHeight);
        int src_x2 = Clamp(AlignTo4Right((float)(i_offsetX+i_rect_width)),0,i_fullWidth);
        int src_y2 = Clamp(AlignTo4Right((float)(i_offsetY+i_rect_height)),0,i_fullHeight);
        //
        processor.BlitMipBlock(m,out_width,out_height,dest_offsetx,dest_offsety,dest_x2,dest_y2,src_offsetx,src_offsety,src_x2,src_y2,src_width[n],src_height[n],&data[0]);
        //
        o_fullWidth >>=1;
        o_fullHeight >>=1;
        o_offsetx >>=1;
        o_offsety >>=1;
        o_rect_width >>=1;
        o_rect_height >>=1;
        //
        if( i_rect_width>o_rect_width || i_rect_height>o_rect_height )
        {
          i_offsetX >>=1;
          i_offsetY >>=1;
          i_rect_width >>=1;
          i_rect_height >>=1;
          i_fullWidth >>=1;
          i_fullHeight >>=1;
          if( i_rect_width<4 )
          {
            i_rect_width = 4;
          }
          if( i_rect_height<4 )
          {
            i_rect_height = 4;
          }
        }
        if( o_rect_width<4 && o_rect_height<4 )
        {
          break;
        }
      }
    }
  }
  //
  CImageExtensionHelper::DDS_HEADER ddsh;
  ZeroStruct(ddsh);
  ddsh.dwSize = sizeof(CImageExtensionHelper::DDS_HEADER);
  ddsh.dwWidth	= out_width;
  ddsh.dwHeight = out_height;
  ddsh.dwMipMapCount = numOutMips>1 ? numOutMips : 0;
  ddsh.ddspf = outputFormat;
  ddsh.dwHeaderFlags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_MIPMAP;
  ddsh.dwSurfaceFlags = DDS_SURFACE_FLAGS_TEXTURE | DDS_SURFACE_FLAGS_MIPMAP;
  //
  FILE* pRawFile = gEnv->pCryPak->FOpen(output_filename,"wb");
  if( !pRawFile )
    return false;
  //
  DWORD dwMagic = MAKEFOURCC('D','D','S',' ');
  gEnv->pCryPak->FWrite(&dwMagic,sizeof(dwMagic),1,pRawFile);
  gEnv->pCryPak->FWrite(&ddsh,sizeof(ddsh),1,pRawFile);
  gEnv->pCryPak->FWrite(&data[0],data.size(),1,pRawFile);
  gEnv->pCryPak->FClose(pRawFile);
  //
  return true;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////

void IRenderer::SDrawCallCountInfo::Update( CRenderObject *pObj, IRenderMesh *pRM )
{
  SRenderPipeline& RESTRICT_REFERENCE rRP = gRenDev->m_RP;
  if( ((IRenderNode *)pObj->m_pRenderNode) )
	{
		//m_pRenderNode->GetPos() can cause a pure virtual call
		pPos = pObj->GetTranslation();

		if(!pRenderMesh)
		{
			pRenderMesh = pRM;
		}

		if( rRP.m_nBatchFilter & (FB_GLOW|FB_SCATTER|FB_MOTIONBLUR|FB_CAUSTICS|FB_CUSTOM_RENDER|FB_POST_3D_RENDER|FB_LAYER_EFFECT|FB_SOFTALPHATEST|FB_DEBUG) )
			nMisc++;
		else
			if( !(rRP.m_TI[rRP.m_nProcessThreadID].m_PersFlags & RBPF_SHADOWGEN) )
			{
				if( rRP.m_nBatchFilter & FB_GENERAL )
				{
					if( rRP.m_nPassGroupID == EFSLIST_TRANSP)
					{
						nTransparent++;
					}
					else
					{
						nGeneral++;
					}
				}
				else if( rRP.m_nBatchFilter & FB_Z )
				{
					nZpass++;
				}
			}
			else
				nShadows++;
	}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////

void S3DEngineCommon::Update(int nThreadID)
{
	I3DEngine *p3DEngine = gEnv->p3DEngine;

  // Camera vis area
  IVisArea *pCamVisArea =  p3DEngine->GetVisAreaFromPos( gRenDev->GetRCamera().Orig );
  m_pCamVisAreaInfo.nFlags &= ~VAF_MASK;
  if( pCamVisArea )
  {
    m_pCamVisAreaInfo.nFlags |= VAF_EXISTS_FOR_POSITION;
    if( pCamVisArea->IsConnectedToOutdoor() )
      m_pCamVisAreaInfo.nFlags |= VAF_CONNECTED_TO_OUTDOOR;
    if( pCamVisArea->IsAffectedByOutLights() )
      m_pCamVisAreaInfo.nFlags |= VAF_AFFECTED_BY_OUT_LIGHTS;
  }

	// Update ocean info
	m_OceanInfo.m_fWaterLevel = p3DEngine->GetWaterLevel( &gRenDev->GetRCamera().Orig );
	m_OceanInfo.m_nOceanRenderFlags = p3DEngine->GetOceanRenderFlags();
	m_OceanInfo.m_vCausticsParams = p3DEngine->GetCausticsParams();

	if (CRenderer::CV_r_rain || CRenderer::CV_r_snow)
	{
		const int nFrmID = gRenDev->GetFrameID();
		if (m_RainInfo.m_nLastFrameUpdate != nFrmID)
		{
			if(CRenderer::CV_r_rain)
				UpdateRainInfo(nThreadID);
			if(CRenderer::CV_r_snow)
				UpdateSnowInfo(nThreadID);
			m_RainInfo.m_nLastFrameUpdate = nFrmID;
		}
	}

	// Release rain occluders
	if (CRenderer::CV_r_rain < 2 && CRenderer::CV_r_snow < 2)
	{
		m_RainOccluders.Release();
		stl::free_container(m_RainOccluders.m_arrCurrOccluders[nThreadID]);
		m_RainInfo.m_bApplyOcclusion = false;
	}
}

void S3DEngineCommon::UpdateRainInfo(int nThreadID)
{
	gEnv->p3DEngine->GetRainParams(m_RainInfo.m_vWorldPos, m_RainInfo.m_fRadius, m_RainInfo.m_fAmount, m_RainInfo.m_vColor);

	const Vec3 vCamPos = gRenDev->GetRCamera().Orig;
	const float fUnderWaterAtten = clamp_tpl(vCamPos.z - m_OceanInfo.m_fWaterLevel + 1.f, 0.f, 1.f);
	m_RainInfo.m_fAmount *= fUnderWaterAtten;

//#define RAIN_DEBUG
#ifndef RAIN_DEBUG
	if (m_RainInfo.m_fAmount < 0.05f)
		return;
#endif

	gEnv->p3DEngine->GetRainParams(m_RainInfo.m_fReflectionAmount, m_RainInfo.m_fFakeGlossiness, m_RainInfo.m_fPuddelsAmount, m_RainInfo.m_bRainDrops, m_RainInfo.m_fRainDropsSpeed, m_RainInfo.m_fUmbrellaRadius);

#ifdef RAIN_DEBUG
	m_RainInfo.m_bRainDrops = true;
	m_RainInfo.m_fRainDropsSpeed = 1.f;
	m_RainInfo.m_fAmount = 1.f;
	m_RainInfo.m_fFakeGlossiness = 1.f;
	m_RainInfo.m_fPuddelsAmount = 3.f;
	m_RainInfo.m_fRadius = 2000.f;
	m_RainInfo.m_fReflectionAmount = 0.5f;
	m_RainInfo.m_fUmbrellaRadius = 0.f;
	m_RainInfo.m_vColor.Set(1,1,1);
	m_RainInfo.m_vWorldPos.Set(0,0,0);
#endif

	UpdateRainOccInfo(nThreadID);
}

void S3DEngineCommon::UpdateSnowInfo(int nThreadID)
{
	gEnv->p3DEngine->GetSnowSurfaceParams(m_SnowInfo.m_vWorldPos, m_SnowInfo.m_fRadius, m_SnowInfo.m_fSnowAmount, m_SnowInfo.m_fFrostAmount, m_SnowInfo.m_fSurfaceFreezing);
	gEnv->p3DEngine->GetSnowFallParams(m_SnowInfo.m_nSnowFlakeCount, m_SnowInfo.m_fSnowFlakeSize, m_SnowInfo.m_fSnowFallBrightness, m_SnowInfo.m_fSnowFallGravityScale, m_SnowInfo.m_fSnowFallWindScale, m_SnowInfo.m_fSnowFallTurbulence, m_SnowInfo.m_fSnowFallTurbulenceFreq);

	//#define RAIN_DEBUG
#ifndef RAIN_DEBUG
	if (m_SnowInfo.m_fSnowAmount < 0.05f && m_SnowInfo.m_fFrostAmount < 0.05f)
		return;
#endif

	UpdateRainOccInfo(nThreadID);
}

void S3DEngineCommon::UpdateRainOccInfo(int nThreadID)
{
	bool bSnowEnabled = (m_SnowInfo.m_fSnowAmount > 0.05f || m_SnowInfo.m_fFrostAmount > 0.05f) && (m_SnowInfo.m_fRadius > 0.05f) && (CRenderer::CV_r_snow == 2);

	bool bProcessedAll = true;
	const uint32 numGPUs = gRenDev->m_nGPUs > MAX_GPU_NUM ? MAX_GPU_NUM : gRenDev->m_nGPUs;
	for (uint32 i = 0; i < numGPUs; ++i)
		bProcessedAll &= m_RainOccluders.m_bProcessed[i];
	const bool bUpdateOcc = m_RainOccluders.m_bForceUpdate || bProcessedAll;
	if (bUpdateOcc)
		m_RainOccluders.Release();

	const Vec3 vCamPos = gRenDev->GetRCamera().Orig;

	if (CRenderer::CV_r_rain == 2 || bSnowEnabled)
	{
		N3DEngineCommon::ArrOccluders & arrOccluders = m_RainOccluders.m_arrOccluders;
		if (bUpdateOcc)
		{
			// Choose world position and radius.
			// Snow takes priority since occlusion has a much stronger impact on it.
			Vec3 vWorldPos = bSnowEnabled ? m_SnowInfo.m_vWorldPos : m_RainInfo.m_vWorldPos;
			float fRadius = bSnowEnabled ? m_SnowInfo.m_fRadius : m_RainInfo.m_fRadius;
			float fViewerArea = bSnowEnabled ? 128.f : 32.f; // Snow requires further view distance, otherwise obvious "unoccluded" snow regions become visible.
			float fOccArea = fViewerArea;

			// Rain volume BB
			AABB bbRainVol(fRadius);
			bbRainVol.Move(vWorldPos);
			// Visible area BB
			AABB bbViewer(fViewerArea);
			bbViewer.Move(vCamPos);
			// Area around viewer/rain source BB
			AABB bbArea(bbViewer);
			bbArea.ClipToBox(bbRainVol);
			// Snap BB to grid
			Vec3 vSnapped = bbArea.min / 16.f;
			bbArea.min.Set(floor_tpl(vSnapped.x), floor_tpl(vSnapped.y), floor_tpl(vSnapped.z));
			bbArea.min *= 16.f;
			vSnapped = bbArea.max / 16.f;
			bbArea.max.Set(ceil_tpl(vSnapped.x), ceil_tpl(vSnapped.y), ceil_tpl(vSnapped.z));
			bbArea.max *= 16.f;

			// If occlusion map info dirty
			static float fOccTreshold = CRenderer::CV_r_rainOccluderSizeTreshold;
			static float fOldRadius = fRadius;
			const AABB & oldAreaBounds = m_RainInfo.m_AreaAABB;
			if (!oldAreaBounds.min.IsEquivalent(bbArea.min)
				|| !oldAreaBounds.max.IsEquivalent(bbArea.max)
				|| fOldRadius != fRadius
				|| fOccTreshold != CRenderer::CV_r_rainOccluderSizeTreshold
				|| m_RainOccluders.m_bForceUpdate)
			{
				// Get occluders inside area
				unsigned int nOccluders(0);

				EERType eFilterType = eERType_Brush;
				nOccluders = gEnv->p3DEngine->GetObjectsByTypeInBox(eFilterType, bbArea);
				std::vector<IRenderNode *> occluders(nOccluders, NULL);
				if (nOccluders)
					gEnv->p3DEngine->GetObjectsByTypeInBox(eFilterType, bbArea, &occluders.front());

				// Set to new values, will be needed for other rain passes
				m_RainInfo.m_AreaAABB = bbArea;
				fOccTreshold = CRenderer::CV_r_rainOccluderSizeTreshold;
				fOldRadius = fRadius;

				AABB geomBB(AABB::RESET);
				static const size_t nMAX_OCCLUDERS = bSnowEnabled ? 768 : 512;
				const size_t occluderLimit = min((size_t)nOccluders, nMAX_OCCLUDERS);
				arrOccluders.resize(occluderLimit);
				// Filter occluders and get bounding box
				for (std::vector<IRenderNode *>::const_iterator it = occluders.begin();
					it != occluders.end() && m_RainOccluders.m_nNumOccluders < occluderLimit;
					it++)
				{
					IRenderNode * pRndNode = *it;
					if (pRndNode)
					{
						const AABB & aabb = pRndNode->GetBBox();
						const Vec3 vDiag = aabb.max - aabb.min;
						const float fSqrFlatRadius = Vec2(vDiag.x, vDiag.y).GetLength2();
						const unsigned nRndNodeFlags = pRndNode->GetRndFlags();
						// TODO: rainoccluder should be the only flag tested
						// (ie. enabled ONLY for small subset of geometry assets - means going through all assets affected by rain)
						if ((fSqrFlatRadius < CRenderer::CV_r_rainOccluderSizeTreshold)
							|| !(nRndNodeFlags & ERF_RAIN_OCCLUDER)
							|| (nRndNodeFlags & (ERF_COLLISION_PROXY | ERF_RAYCAST_PROXY | ERF_HIDDEN | ERF_PICKABLE)))
							continue;

						N3DEngineCommon::SRainOccluder rainOccluder;
						IStatObj * pObj = pRndNode->GetEntityStatObj(0, 0, &rainOccluder.m_WorldMat);
						if (pObj)
						{
							const size_t nPrevIdx = m_RainOccluders.m_nNumOccluders;
							if (pObj->GetFlags() & STATIC_OBJECT_COMPOUND)
							{
								const Matrix34A matParentTM = rainOccluder.m_WorldMat;
								int nSubCount = pObj->GetSubObjectCount();
								for (int nSubId = 0; nSubId < nSubCount && m_RainOccluders.m_nNumOccluders < occluderLimit; nSubId++)
								{
									IStatObj::SSubObject * pSubObj = pObj->GetSubObject(nSubId);
									if (pSubObj->bIdentityMatrix)
										rainOccluder.m_WorldMat = matParentTM;
									else
										rainOccluder.m_WorldMat = matParentTM * pSubObj->localTM;

									IStatObj * pSubStatObj = pSubObj->pStatObj;
									if (pSubStatObj && pSubStatObj->GetRenderMesh())
									{
										rainOccluder.m_RndMesh = pSubStatObj->GetRenderMesh();
										arrOccluders[m_RainOccluders.m_nNumOccluders++] = rainOccluder;
									}
								}
							}
							else if (pObj->GetRenderMesh())
							{
								rainOccluder.m_RndMesh = pObj->GetRenderMesh();
								arrOccluders[m_RainOccluders.m_nNumOccluders++] = rainOccluder;
							}

							if (m_RainOccluders.m_nNumOccluders > nPrevIdx)
								geomBB.Add(pRndNode->GetBBox());
						}
					}
				}
				const bool bProcess = m_RainOccluders.m_nNumOccluders == 0;
				for (uint32 i = 0; i < numGPUs; ++i)
					m_RainOccluders.m_bProcessed[i] = bProcess;
				m_RainOccluders.m_bForceUpdate = false;
				m_RainInfo.m_bApplyOcclusion = m_RainOccluders.m_nNumOccluders > 0;

				geomBB.ClipToBox(bbArea);
				// Clip to ocean level
				geomBB.min.z = max(geomBB.min.z, gEnv->p3DEngine->GetWaterLevel()) - 0.5f;

				Vec3 vSnappedCenter = bbArea.GetCenter() / 16;
				vSnappedCenter.Set(floor_tpl(vSnappedCenter.x), floor_tpl(vSnappedCenter.y), floor_tpl(vSnappedCenter.z));
				vSnappedCenter *= 16;

				AABB occBB(fOccArea);
				occBB.Move(vSnappedCenter);
				occBB.min.z = max(occBB.min.z, geomBB.min.z);
				occBB.max.z = min(occBB.max.z, geomBB.max.z);

				// Get occlusion transformation matrix
				Matrix44 & matOccTrans = m_RainInfo.m_matOccTrans;
				Matrix44 matScale;
				matOccTrans.SetIdentity();
				matOccTrans.SetTranslation(-occBB.min);
				matScale.SetIdentity();
				const Vec3 vScale(occBB.max - occBB.min);
				matScale.m00 = 1.f / vScale.x;
				matScale.m11 = 1.f / vScale.y;
				matScale.m22 = 1.f / vScale.z;
				matOccTrans.Multiply(matScale, matOccTrans);
			}
		}
		m_RainOccluders.m_arrCurrOccluders[nThreadID].resize(m_RainOccluders.m_nNumOccluders);
		std::copy(arrOccluders.begin(), arrOccluders.begin() + m_RainOccluders.m_nNumOccluders, m_RainOccluders.m_arrCurrOccluders[nThreadID].begin());
	}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
namespace WaterVolumeStaticData { void GetMemoryUsage( ICrySizer *pSizer ); }

void CRenderer::GetMemoryUsage( ICrySizer *pSizer )
{
	// should be called by all derived classes
	for(uint32 i=0; i<RT_COMMAND_BUF_COUNT; ++i)
		pSizer->AddObject( m_TextMessages[i] );
	pSizer->AddObject( m_RP );
	pSizer->AddObject( m_pRT );
	pSizer->AddObject(m_DevBufMan);
	pSizer->AddObject(CRenderObject::m_sFreePermObjData);
	WaterVolumeStaticData::GetMemoryUsage(pSizer);
}

// retrieves the bandwidth calculations for the audio streaming
void CRenderer::GetBandwidthStats(float * fBandwidthRequested)
{
#if !defined (_RELEASE) || defined(ENABLE_STATOSCOPE_RELEASE)
	if ( fBandwidthRequested )
	{
		*fBandwidthRequested = (CTexture::s_nBytesSubmittedToStreaming + CTexture::s_nBytesRequiredNotSubmitted) / 1024.0f;
	}
#endif
}

void CRenderer::GetTextureRequests(float * requests)
{
#if !defined (_RELEASE) || defined(ENABLE_STATOSCOPE_RELEASE)
	float time = gEnv->pTimer->GetAsyncCurTime() - CTexture::s_StreamingRequestsTime;
	*requests = ((float)CTexture::s_StreamingRequestsCount/time);
	CTexture::s_StreamingRequestsTime = gEnv->pTimer->GetAsyncCurTime();
	CTexture::s_StreamingRequestsCount = 0;
#endif
}

void CRenderer::GetTextureRenders(float * renders)
{
#if !defined (_RELEASE) || defined(ENABLE_STATOSCOPE_RELEASE)
	float time = gEnv->pTimer->GetAsyncCurTime() - CTexture::s_TextureUpdatedRenderedTime;
	*renders = ((float)CTexture::s_TexturesUpdatedRendered/time);
	CTexture::s_TextureUpdatedRenderedTime = gEnv->pTimer->GetAsyncCurTime();
	CTexture::s_TexturesUpdatedRendered = 0;
#endif
}

void CRenderer::GetTexturePoolUsage(float * usage)
{
#if !defined (_RELEASE) || defined(ENABLE_STATOSCOPE_RELEASE)
	*usage = ((float)CTexture::s_nStatsCurManagedStreamedTexMem) / 1024.0f / 1024.0f;
#endif
}

void CRenderer::GetTexturePoolWanted(float * wanted)
{
#if !defined (_RELEASE) || defined(ENABLE_STATOSCOPE_RELEASE)
	int currentPoolSize = CTexture::s_nStatsCurManagedStreamedTexMem;
	int requiredMipSize = CTexture::GetRequiredMipMemUsage();
	*wanted = ((float)currentPoolSize + (float)requiredMipSize) / 1024.0f / 1024.0f;
#endif
}

void CRenderer::GetTextureUpdates(float * updates)
{
#if !defined (_RELEASE)
	float time = gEnv->pTimer->GetAsyncCurTime() - CTexture::s_TextureUpdatesTime;
	*updates = ((float)CTexture::s_TextureUpdates/time);
	CTexture::s_TextureUpdatesTime = gEnv->pTimer->GetAsyncCurTime();
	CTexture::s_TextureUpdates = 0;
#endif
}

void CRenderer::SetTextureStreamListener(ITextureStreamListener* pListener)
{
#ifdef ENABLE_TEXTURE_STREAM_LISTENER
	CTexture::s_pStreamListener = pListener;
#endif
}


float CRenderer::GetGPUFrameTime()
{















	float fGPUidle = m_fTimeGPUIdlePercent[m_RP.m_nProcessThreadID] * 0.01f; // normalise %
	float fGPUload = 1.0f - fGPUidle; // normalised non-idle time
	float fGPUtime = (iTimer->GetFrameTime() * fGPUload); //GPU time in seconds
	return fGPUtime;

}

void CRenderer::GetRenderTimes( SRenderTimes &outTimes )
{
	int nThr = m_pRT->GetThreadList();
	//Query render times on main thread
	outTimes.fWaitForMain = m_fTimeWaitForMain[nThr];
	outTimes.fWaitForRender = m_fTimeWaitForRender[nThr];
	outTimes.fWaitForGPU = m_fTimeWaitForGPU[nThr]; 
	outTimes.fTimeProcessedRT = m_fTimeProcessedRT[nThr];
	outTimes.fTimeProcessedRTScene = m_RP.m_PS[nThr].m_fRenderTime;
	outTimes.fTimeGPUIdlePercent = m_fTimeGPUIdlePercent[nThr];
}

//////////////////////////////////////////////////////////////////////////
void CRenderer::PreShutDown()
{
	if (m_pTextureManager)
		m_pTextureManager->ReleaseDefaultTextures();
}

//////////////////////////////////////////////////////////////////////////
void CRenderer::PostShutDown()
{
	SAFE_DELETE(m_pTextureManager);
}

//////////////////////////////////////////////////////////////////////////
void CRenderer::UpdateRenderingModesInfo()
{
	s_AllowMotionBlur = CV_r_MotionBlur;

	CPostEffectsMgr *pPostEffectMgr = PostEffectMgr();
  if (!pPostEffectMgr || !pPostEffectMgr->IsCreated())
    return;

	CThermalVision *pThermalVision = (CThermalVision *)pPostEffectMgr->GetEffect(ePFX_ThermalVision);
	CPostEffect *pSonarVision = pPostEffectMgr->GetEffect(ePFX_SonarVision);
	CPostEffect *pNightVision = pPostEffectMgr->GetEffect(ePFX_NightVision);

	//if( m_nThermalVisionMode = (pThermalVision->IsActive() && CV_r_ThermalVision || CV_r_ThermalVision == 2) )
	//{
	//	m_nSonarVisionMode = m_nNightVisionMode = 0;
	//	return;
	//}

	if( m_nSonarVisionMode = (pSonarVision->IsActive() && CV_r_SonarVision || CV_r_SonarVision == 2) )
	{
		m_nNightVisionMode = 0;
		m_nThermalVisionMode = 0;
		return;
	}

	m_nNightVisionMode = (pNightVision->IsActive() && (CV_r_NightVision == 2) || (CV_r_NightVision == 3)) && gRenDev->IsHDRModeEnabled(); // check only for HDR version

	if( !m_nNightVisionMode && pThermalVision->GetTransitionEffectState() )
		m_nThermalVisionMode = 0;
	else
		m_nThermalVisionMode = m_nNightVisionMode;
}

//////////////////////////////////////////////////////////////////////////

bool CRenderer::IsCustomRenderModeEnabled(uint32 nRenderModeMask )
{
	assert( nRenderModeMask );

	if ( !CV_r_PostProcess )
		return false;

	if( (nRenderModeMask & eRMF_MASK) == eRMF_MASK )
		return m_nThermalVisionMode != 0 || m_nSonarVisionMode != 0 || m_nNightVisionMode!= 0;
	if( nRenderModeMask & eRMF_THERMALVISION )
		return m_nThermalVisionMode != 0;
	if( nRenderModeMask & eRMF_SONARVISION )
		return m_nSonarVisionMode != 0;
	if( nRenderModeMask & eRMF_NIGHTVISION )
		return m_nNightVisionMode != 0;

	return false;
}

//////////////////////////////////////////////////////////////////////////
bool CRenderer::IsPost3DRendererEnabled() const
{
	CPostEffectsMgr *pPostEffectMgr = PostEffectMgr();
	if(!pPostEffectMgr || !pPostEffectMgr->IsCreated())
		return false;

	CPostEffect* pPost3DRenderer = pPostEffectMgr->GetEffect(ePFX_Post3DRenderer);
	if(pPost3DRenderer)
	{
		return pPost3DRenderer->IsActive();
	}

	return false;
}

//////////////////////////////////////////////////////////////////////////
void CRenderer::EF_SetPostEffectParam(const char *pParam, float fValue, bool bForceValue)
{
	if(pParam && m_RP.m_pREPostProcess )
		m_RP.m_pREPostProcess->mfSetParameter(pParam, fValue, bForceValue); 
}

void CRenderer::EF_SetPostEffectParamVec4(const char *pParam, const Vec4 &pValue, bool bForceValue)
{
	if(pParam && m_RP.m_pREPostProcess )
		m_RP.m_pREPostProcess->mfSetParameterVec4(pParam, pValue, bForceValue); 
}


//////////////////////////////////////////////////////////////////////////
void CRenderer::EF_SetPostEffectParamString(const char *pParam, const char *pszArg)
{
	if(pParam && pszArg && m_RP.m_pREPostProcess )
		m_RP.m_pREPostProcess->mfSetParameterString(pParam, pszArg); 
}

//////////////////////////////////////////////////////////////////////////
void CRenderer::EF_GetPostEffectParam(const char *pParam, float &fValue)
{
	if(pParam && m_RP.m_pREPostProcess )
		m_RP.m_pREPostProcess->mfGetParameter(pParam, fValue); 
}

//////////////////////////////////////////////////////////////////////////
void CRenderer::EF_GetPostEffectParamVec4(const char *pParam, Vec4 &pValue)
{
	if(pParam && m_RP.m_pREPostProcess )
		m_RP.m_pREPostProcess->mfGetParameterVec4(pParam, pValue); 

}

//////////////////////////////////////////////////////////////////////////
void CRenderer::EF_GetPostEffectParamString(const char *pParam, const char *&pszArg)
{
	if(pParam && pszArg && m_RP.m_pREPostProcess )
		m_RP.m_pREPostProcess->mfGetParameterString(pParam, pszArg); 

}

//////////////////////////////////////////////////////////////////////////
int32 CRenderer::EF_GetPostEffectID(const char* pPostEffectName)
{
	if(pPostEffectName && m_RP.m_pREPostProcess )
		return m_RP.m_pREPostProcess->mfGetPostEffectID(pPostEffectName); 
	return ePFX_Invalid;
}

//////////////////////////////////////////////////////////////////////////
void CRenderer::EF_ResetPostEffects(bool bOnSpecChange)
{
  m_pRT->RC_ResetPostEffects(bOnSpecChange);
}

//////////////////////////////////////////////////////////////////////////
void CRenderer::EF_AddPostEffectLight(CDLight &pLight)
{
	if (m_RP.m_pREPostProcess)
		m_RP.m_pREPostProcess->AddLight(pLight);
}


////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////


void CRenderer::EF_AddWaterSimHit(const Vec3 &vPos)
{	
	if(PostEffectMgr() == NULL)
		return;

	CPostEffectsMgr *pPostEffectsMgr = PostEffectMgr();
	if(pPostEffectsMgr)
	{
		CWaterRipples *pWaterRipplesTech = (CWaterRipples *)pPostEffectsMgr->GetEffect(ePFX_WaterRipples);
		if( pWaterRipplesTech )
			pWaterRipplesTech->AddHit(vPos);
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CRenderer::SetTexturePrecaching(bool stat)
{
	CTexture::s_bPrecachePhase = stat;
}

//////////////////////////////////////////////////////////////////////////
#if !defined _RELEASE
void CRenderer::AddTexturePoolAllocation(int size, string texturepath)
{
  ScopedSwitchToGlobalHeap useGlobalHeap;
	m_texturePoolAllocationList[m_RP.m_nFillThreadID].push_back(new STexturePoolAllocation(size,texturepath));
}

std::vector<STexturePoolAllocation*> * CRenderer::GetTexturePoolAllocationList()
{
	return &m_texturePoolAllocationList[m_RP.m_nProcessThreadID];
}

void CRenderer::ClearTexturePoolAllocationList(int threadid)
{
	if ( threadid == -1 )
		threadid = m_RP.m_nProcessThreadID;

	//clear allocation list once all are added to the record
	while(m_texturePoolAllocationList[threadid].size() > 0)
	{
		STexturePoolAllocation * item = m_texturePoolAllocationList[threadid].back();
		delete item;
		item = NULL;
		m_texturePoolAllocationList[threadid].pop_back();
	}
	stl::free_container(m_texturePoolAllocationList[threadid]);
}
#endif

#if SUPPORT_RENDER_TO_CONTROLLER
void CRenderer::RT_InitialiseControllerRenderer()
{
	m_renderToScreenOnController->Init();
}

void CRenderer::RT_UpdateControllerRenderer()
{
  if (m_renderToScreenOnController)
	  m_renderToScreenOnController->DoRender();
}
void CRenderer::RenderToController()
{
	m_pRT->RC_UpdateControllerRenderer();
}
#endif

//////////////////////////////////////////////////////////////////////////










Matrix44A CRenderer::GetCameraMatrix()
{
	static const Matrix33 matRotX = Matrix33::CreateRotationX(-gf_PI/2);
	Matrix34 matCam = GetCamera().GetMatrix();
	matCam.SetTranslation(matCam.GetTranslation() + m_vSegmentedWorldOffset);
	Matrix44A matView = GetTransposed44(Matrix44A(matRotX * matCam.GetInverted()));
	return matView;
}

void CRenderer::OffsetPosition(const Vec3 &delta)
{
#ifdef SEG_WORLD
	m_vSegmentedWorldOffset = delta;
#endif
}

#include UNIQUE_VIRTUAL_WRAPPER(IShaderPublicParams)
